Define demographic
variables
Need to check
datasets with Rcihi (why do we have QC in L1? Am I using not the latest
dataset?)
all <- filtered
demographics_var <- c("Age","Gender","L1","speak.other.L2","study.other.L2","origins","year.studyL2","other5.other.ways","degree","roleL2.degree","study.year","prof","L2.VCE","uni1.year","Context")
l2School <- "\\.L2school$"
l2School_variables <- colnames(all)[grep(l2School,colnames(all))]
ggplot(all,aes(x=L1,fill=Context)) + geom_bar() + coord_flip() + ggtitle("First Language") + labs(y="N. of participants",x="") + theme_bw()

table(all$L1,all$Context)
English in Germany English in Italy German in Australia Italian in Australia
Afrikaans 0 0 1 0
Albanian 0 1 0 0
Cantonese 0 0 2 0
Chinese 0 2 2 0
Dutch 1 0 0 0
English 1 0 75 73
English and Dutch 0 0 2 0
German 64 0 0 0
German and English 1 0 1 0
I 0 0 0 1
Indonesian 0 0 1 0
Italian 0 87 0 0
Japanese 0 0 1 0
Mandarin 0 0 1 1
Persian (Farsi) 0 0 1 0
Romanian 0 0 1 0
Russian 2 0 0 0
Sindhi 0 0 1 0
Spanish 1 0 0 0
Turkish 1 0 0 0
Ukrainian 0 1 0 0
table(all$degree,all$L1)
Afrikaans Albanian Cantonese Chinese Dutch English English and Dutch German German and English I
BA in Anglistik 0 0 0 0 0 1 0 34 1 0
BA in Nordamerikastudien 0 0 0 0 0 0 0 4 0 0
HUM 1 0 2 0 0 93 1 0 0 1
HUM.SCI 0 0 0 0 0 6 0 0 0 0
LA 0 0 0 0 1 0 0 25 0 0
Lingue e letterature straniere 0 1 0 1 0 0 0 0 0 0
Lingue, mercati e culture dell'Asia 0 0 0 1 0 0 0 0 0 0
SCI 0 0 0 2 0 47 1 0 1 0
Indonesian Italian Japanese Mandarin Persian (Farsi) Romanian Russian Sindhi Spanish Turkish
BA in Anglistik 0 0 0 0 0 0 2 0 1 0
BA in Nordamerikastudien 0 0 0 0 0 0 0 0 0 0
HUM 0 0 0 0 0 0 0 0 0 0
HUM.SCI 0 0 0 0 0 0 0 0 0 0
LA 0 0 0 0 0 0 0 0 0 1
Lingue e letterature straniere 0 75 0 0 0 0 0 0 0 0
Lingue, mercati e culture dell'Asia 0 12 0 0 0 0 0 0 0 0
SCI 1 0 1 2 1 1 0 1 0 0
Ukrainian
BA in Anglistik 0
BA in Nordamerikastudien 0
HUM 0
HUM.SCI 0
LA 0
Lingue e letterature straniere 1
Lingue, mercati e culture dell'Asia 0
SCI 0
- Check for L1 but we decided not to filter for it
#Filter by L1
nc <- names(table(all$Context))
table(all$Context)
English in Germany English in Italy German in Australia Italian in Australia
72 91 89 75
l1_filter <- all[(all$Context == nc[1] & (all$L1 == "German" | all$L1 == "German and English")) |
(all$Context == nc[2] & (all$L1 == "Italian")) |
(all$Context == nc[3] & (all$L1 == "English" | all$L1 == "English and Dutch" | all$L1 == "German and English")) |
(all$Context == nc[4] & (all$L1 == "English" | all$L1 == "English and Dutch" | all$L1 == "German and English")),]
#all <- l1_filter
# do not filter for L1
all <- all
# subset demographics
demo <- subset(all,select=c("Resp.ID",demographics_var,l2School_variables))
# Numeri finali
table(l1_filter$Context)
English in Germany English in Italy German in Australia Italian in Australia
65 87 78 73
table(all$Context)
English in Germany English in Italy German in Australia Italian in Australia
72 91 89 75
- Filter missing value:
- Filter participants who didn’t put the degree
- we don’t care about speak.other.L2 and study.other.L2
missing_bySample <- rowSums(is.na(demo))
names(missing_bySample) <- demo$Resp.ID
missing_byVar <- colSums(is.na(demo))
names(missing_byVar) <- colnames(demo)
barplot(missing_bySample)

d <- data.frame(miss=missing_byVar)
d$varID <- rownames(d)
ggplot(data=d,aes(x=varID,y=miss)) + geom_bar(stat="identity") + theme_bw() +theme(axis.text.x = element_text(angle = 45, hjust = 1))

demo_missing <- demo %>% group_by(Context) %>% summarise(roleL2.degree_na = sum(is.na(roleL2.degree)),
L2.VCE_na = sum(is.na(L2.VCE)),
other5.other.ways_na=sum(is.na(other5.other.ways )),
uni1.year_na = sum(is.na(uni1.year)),
primary1.L2school_na=sum(is.na(primary1.L2school)),
CLS3.L2school_na = sum(is.na(CLS3.L2school)),
VSL4.L2school_na=sum(is.na(VSL4.L2school)),
degree = sum(is.na(degree)),
schooL2country5.L2school_na=sum(is.na(schooL2country5.L2school)))
# We do not filter for speak.other.L2 or study.other.L2
#demo[is.na(demo$speak.other.L2),]
# teniamo
#demo[is.na(demo$study.other.L2),]
missing_bySample[names(missing_bySample) == "5166861581"]
5166861581
10
#demo[is.na(demo$year.studyL2),]
missing_bySample[names(missing_bySample) == "5378798787"]
5378798787
3
# remove NA from degree
#table(demo$degree,useNA = "always")
# Remove people
all <- all[!is.na(all$degree),]
Stats about filtered
dataset
kable(table(all$Context))
| English in Germany |
70 |
| English in Italy |
91 |
| German in Australia |
88 |
| Italian in Australia |
74 |
kable(table(all$study.year))
| 1st semester |
70 |
| 1st year |
253 |
kable(table(all$year.studyL2))
| 0 years |
33 |
| 1- 3 years |
9 |
| 1-3 years |
7 |
| 4-6 years |
53 |
| First year of primary school |
73 |
| Kindergarten |
29 |
| Less than a year |
18 |
| more than 6 years |
41 |
| Other |
59 |
Recoded demographic
variables
recoded_dem_richi <- read_excel("02-descriptive_data/21 03 merged_filtered_imputedMedian_likertNumber.xlsx")
Write filtered and
merged dataset
write.csv(all,file.path("02-descriptive_data/context-merged_filtered.csv"))
Descriptive plots and
tables
all$speak.other.L2_binary <- ifelse(!is.na(all$speak.other.L2) &
!(all$speak.other.L2 %in% c("Yes","No")),"Yes",as.character(all$speak.other.L2))
kable(table(all$speak.other.L2_binary,all$Context,useNA = "always"))
| No |
12 |
24 |
52 |
53 |
0 |
| Yes |
57 |
67 |
36 |
20 |
0 |
| NA |
1 |
0 |
0 |
1 |
0 |
NA
tabAge <- t(table(all$Age,all$Context))
ggdf <- data.frame(Age = rep(colnames(tabAge),each=4)[!(as.numeric(tabAge) == 0)],
N.Participants = as.numeric(tabAge)[!(as.numeric(tabAge) == 0)],
Context = rep(rownames(tabAge),times=3)[!(as.numeric(tabAge) == 0)])
ggplot(ggdf,aes(x=Age,y=N.Participants,fill=Context)) + geom_bar(position="dodge",colour="white",stat="identity") + scale_y_continuous(breaks=seq(0,90,10),limits=c(0,90)) + theme_bw() + ggtitle("Participants by age")+
geom_text(aes(label = N.Participants), hjust=0.5, vjust=-0.25, size = 2.5,position=position_dodge(width=0.9))

# add numbers on the bar
tabAge <- t(table(all$Gender,all$Context))
ggdf <- data.frame(Gender = rep(colnames(tabAge),each=4)[!(as.numeric(tabAge) == 0)],
N.Participants = as.numeric(tabAge)[!(as.numeric(tabAge) == 0)],
Context = rep(rownames(tabAge),times=3)[!(as.numeric(tabAge) == 0)])
ggplot(ggdf,aes(x=Gender,y=N.Participants,fill=Context)) + geom_bar(position="dodge",colour="white",stat="identity") + labs(y="N participants") + scale_y_continuous(breaks=seq(0,90,10),limits=c(0,90)) + theme_bw() + ggtitle("Participants by gender")+ geom_text(aes(label = N.Participants), hjust=0.5, vjust=-0.25, size = 2.5,position=position_dodge(width=0.9))

# add numbers on the bar
tabAge <- t(table(all$origins,all$Context))
ggplot(all,aes(x=origins,fill=Context)) + geom_bar(position="dodge",colour="white") + ggtitle("Origins by context") + scale_y_continuous(breaks=seq(0,90,10),limits=c(0,90)) + theme_bw() + draw_grob(tableGrob(tabAge), x=2, y=60, width=0.3, height=0.4) + ggtitle("Participants by origins")

tabAge
No Yes
English in Germany 65 5
English in Italy 90 1
German in Australia 63 25
Italian in Australia 36 38
tabAge <- t(table(all$prof,all$Context))
ggplot(all,aes(x=Context,fill=prof)) + geom_bar(position="dodge",colour="white") + ggtitle("Proficiency by context") + scale_y_continuous(breaks=seq(0,90,10),limits=c(0,90)) + theme_bw() + draw_grob(tableGrob(tabAge), x=2, y=80, width=0.3, height=0.4)

tabAge
Advanced Elementary Intermediate Upper-intermediate
English in Germany 38 0 5 27
English in Italy 23 2 9 57
German in Australia 4 32 25 27
Italian in Australia 0 29 29 16
tabAge <- t(table(all[all$Context != "English in Germany" & all$Context != "English in Italy","L2.VCE"],all[all$Context != "English in Germany" & all$Context != "English in Italy",'Context'],useNA = "always"))
tabAge <- tabAge[-3,]
ggplot(all[all$Context != "English in Germany" & all$Context != "English in Italy",],aes(x=Context,fill=L2.VCE)) + geom_bar(position="dodge",colour="white") + ggtitle("L2.VCE by context") + scale_y_continuous(breaks=seq(0,90,10),limits=c(0,90)) + theme_bw() + draw_grob(tableGrob(tabAge), x=2, y=80, width=0.3, height=0.4)

- da mettere a posto con Richi
# year study L2
table(all$year.studyL2,all$other.year.studyL2.richi)
BILINGUAL FIRST.YEAR.SECONDARY FOURTH.YEAR.PRIMARY LOWER.SECONDARY PERSONAL SECOND.YEAR.PRIMARY
0 years 0 0 0 0 0 0
1- 3 years 0 0 0 0 0 0
1-3 years 0 0 0 0 0 0
4-6 years 0 0 0 0 0 0
First year of primary school 0 0 0 0 0 0
Kindergarten 0 0 0 0 0 0
Less than a year 0 0 0 0 0 0
more than 6 years 0 0 0 0 0 0
Other 4 10 5 4 2 2
SECOND.YEAR.SECONDARY THIRD.YEAR.PRIMARY
0 years 0 0
1- 3 years 0 0
1-3 years 0 0
4-6 years 0 0
First year of primary school 0 0
Kindergarten 0 0
Less than a year 0 0
more than 6 years 0 0
Other 2 28
all$year.studyL2 <- ifelse(all$year.studyL2 == "Other",all$other.year.studyL2.richi,all$year.studyL2 )
# European context
ggplot(all[all$Context == "English in Germany" | all$Context == "English in Italy",],aes(x=degree,fill=year.studyL2)) + geom_bar(position="dodge",colour="white") + theme_bw() + ggtitle("Degree by study year L2, by Context") + facet_grid(~Context,scales="free") + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + labs(y = "N participants", x = "degree")

# Australian context
tabAge <- t(table(all[all$Context == "Italian in Australia" | all$Context == "German in Australia",'degree'],all[all$Context == "Italian in Australia" | all$Context == "German in Australia",'Context']))
ggplot(all[all$Context == "Italian in Australia" | all$Context == "German in Australia",],aes(x=Context,fill=degree)) + geom_bar(position="dodge",colour="white") + theme_bw() + ggtitle("Degree in Australian Contexts") + draw_grob(tableGrob(tabAge), x=1., y=40, width=0.3, height=0.4)

tabAge
HUM HUM.SCI SCI
German in Australia 48 4 36
Italian in Australia 50 2 22
# Australian context
tabAge <- t(table(all[all$Context == "English in Italy" | all$Context == "English in Germany",'degree'],all[all$Context == "English in Italy" | all$Context == "English in Germany",'Context']))
ggplot(all[all$Context == "English in Italy" | all$Context == "English in Germany",],aes(x=Context,fill=degree)) + geom_bar(position="dodge",colour="white") + theme_bw() + ggtitle("Degree in European Contexts")

tabAge
BA in Anglistik BA in Nordamerikastudien LA Lingue e letterature straniere Lingue, mercati e culture dell'Asia
English in Germany 39 4 27 0 0
English in Italy 0 0 0 78 13
Likert scales
- Convert Likert scales to numbers
convertToNumber <- function(column){
column <- factor(column,levels = c("Strongly disagree","Disagree","Not sure","Agree","Strongly agree"))
column_number <- as.numeric(column)
return(column_number)
}
table(all$Context)
English in Germany English in Italy German in Australia Italian in Australia
70 91 88 74
table(all$study.year)
1st semester 1st year
70 253
convert_likert <- data.frame(apply(subset(all,select=likert_variables_all),2,convertToNumber))
colnames(convert_likert) <- paste0(colnames(convert_likert),"1")
likert_variables1 <- paste0(likert_variables_all,"1")
# join the converted variables to the filtered dataset
filtered_conv <- cbind(all,convert_likert)
table(filtered_conv[,likert_variables_all[4]],filtered_conv[,likert_variables1[4]],useNA = "always")
1 2 3 4 5 <NA>
Agree 0 0 0 121 0 0
Disagree 0 10 0 0 0 0
Not sure 0 0 39 0 0 0
Strongly agree 0 0 0 0 152 0
Strongly disagree 1 0 0 0 0 0
<NA> 0 0 0 0 0 0
write.csv(filtered_conv,"02-descriptive_data/merged_filtered_likertNumber.csv",row.names = FALSE)
Impute missing values
- Using median values
The missing values appears to be at random and there are max two
missing values in one variable (see plots below). In order not to loose
12 participants while doing the factor analysis across contexts it is
preferable to impute the 12 missing values.
all <- filtered_conv
# Items to use for factor analysis : items shared between contexts
# items to be used for the FA
usable_items <- likert_variables1[!(likert_variables1 %in% c("necessity1","educated1","reconnect.comm1", "speakersmelb.comm1", "comecloser.comm1"))]
rownames(all) <- all$Resp.ID
usable_data_context <- all[,c(usable_items,"Context")]
dat_noNA <- usable_data_context[rowSums(is.na(usable_data_context)) == 0,]
all_noNA <- all[rowSums(is.na(usable_data_context)) == 0,]
table(rowSums(is.na(usable_data_context)))
0 1
311 12
# Participants with NA to remove
table(rowSums(is.na(usable_data_context)),usable_data_context$Context,useNA = "always")
English in Germany English in Italy German in Australia Italian in Australia <NA>
0 70 85 87 69 0
1 0 6 1 5 0
<NA> 0 0 0 0 0
# Variable missing values
table(colSums(is.na(usable_data_context)))
0 1 2
19 10 1
table(rowSums(is.na(usable_data_context)),usable_data_context$Context,useNA = "always")
English in Germany English in Italy German in Australia Italian in Australia <NA>
0 70 85 87 69 0
1 0 6 1 5 0
<NA> 0 0 0 0 0
# check what to use to impute
# have a look at the distribution of missing values
library(mice)
library(VIM)
mice_plot <- aggr(usable_data_context[,usable_items], col=c('navyblue','yellow'),
numbers=TRUE, sortVars=TRUE,
labels=names(usable_data_context[,usable_items]), cex.axis=.4,
gap=1, ylab=c("Missing data","Pattern"),cex.numbers=0.5)
Variables sorted by number of missings:

# Imputing using median
library(Hmisc)
imputedMedian <- usable_data_context
imputedMedian$globalaccess.post1 <- with(imputedMedian[,usable_items], impute(globalaccess.post1, median))
imputedMedian$citizen.post1 <- with(imputedMedian[,usable_items], impute(citizen.post1, median))
imputedMedian$money.instru1 <- with(imputedMedian[,usable_items], impute(money.instru1, median))
imputedMedian$knowledge.instru1 <- with(imputedMedian[,usable_items], impute(knowledge.instru1, median))
imputedMedian$life.intr1 <- with(imputedMedian[,usable_items], impute(life.intr1, median))
imputedMedian$time.integr1 <- with(imputedMedian[,usable_items], impute(time.integr1, median))
imputedMedian$expect.ought1 <- with(imputedMedian[,usable_items], impute(expect.ought1, median))
imputedMedian$job.instru1 <- with(imputedMedian[,usable_items], impute(job.instru1, median))
imputedMedian$career.instru1 <- with(imputedMedian[,usable_items], impute(career.instru1, median))
imputedMedian$meeting.integr1 <- with(imputedMedian[,usable_items], impute(meeting.integr1, median))
imputedMedian$interact.post1 <- with(imputedMedian[,usable_items], impute(interact.post1, median))
# check before after
table(imputedMedian$time.integr1)
2 3 4 5
3 21 95 204
table(usable_data_context$time.integr1)
2 3 4 5
3 21 95 202
table(imputedMedian$life.intr1)
1 2 3 4 5
8 79 81 117 38
table(usable_data_context$life.intr1)
1 2 3 4 5
8 79 80 117 38
table(imputedMedian$knowledge.instru1)
1 2 3 4 5
1 2 29 189 102
table(usable_data_context$knowledge.instru1)
1 2 3 4 5
1 2 29 188 102
table(imputedMedian$money.instru1)
1 2 3 4 5
3 38 179 84 19
table(usable_data_context$money.instru1)
1 2 3 4 5
3 38 178 84 19
table(imputedMedian$citizen.post1)
1 2 3 4 5
3 22 75 148 75
table(usable_data_context$citizen.post1)
1 2 3 4 5
3 22 75 147 75
table(imputedMedian$globalaccess.post1)
1 2 3 4 5
1 3 20 159 140
table(usable_data_context$globalaccess.post1)
1 2 3 4 5
1 3 20 158 140
table(imputedMedian$expect.ought1)
1 2 3 4 5
126 142 30 21 4
table(usable_data_context$expect.ought1)
1 2 3 4 5
126 141 30 21 4
table(imputedMedian$job.instru1)
2 3 4 5
13 103 133 74
table(usable_data_context$job.instru1)
2 3 4 5
13 103 132 74
table(imputedMedian$career.instru1)
1 2 3 4 5
1 1 63 131 127
table(usable_data_context$career.instru1)
1 2 3 4 5
1 1 63 130 127
table(imputedMedian$meeting.integr1)
2 3 4 5
1 10 121 191
table(usable_data_context$meeting.integr1)
2 3 4 5
1 10 121 190
table(imputedMedian$interact.post1)
2 3 4 5
1 19 140 163
table(usable_data_context$interact.post1)
2 3 4 5
1 19 140 162
- Substitute imputed data for the common variables to be used in the
Factor Analysis
all <- all[,!(colnames(all) %in% usable_items)]
imputedMedian$Context <- NULL
sum(!(colnames(imputedMedian) %in% usable_items))
[1] 0
all <- cbind(all,imputedMedian[match(rownames(imputedMedian),all$Resp.ID),])
Add some updates that Richi did in Date 7th June
2018
> Other_ways_and_degree_role_with_respondent_IDs <- read_excel("Other-ways-and-degree-role-with-respondent-IDs.xlsx")
> sum(Other_ways_and_degree_role_with_respondent_IDs$Resp.ID != Other_ways_and_degree_role_with_respondent_IDs$Resp.ID__1)
> # to replace
> # match for the NA degree.role
>
> match_updates <- match(all$Resp.ID,Other_ways_and_degree_role_with_respondent_IDs$Resp.ID)
> all$private.lessons1.other.ways[match_updates] <- Other_ways_and_degree_role_with_respondent_IDs$private.lessons1.other.ways
> all$study.holiday2.other.ways[match_updates] <- Other_ways_and_degree_role_with_respondent_IDs$study.holiday2.other.ways
> all$year.sem.abroad3.other.ways[match_updates] <- Other_ways_and_degree_role_with_respondent_IDs$year.sem.abroad3.other.ways
> all$online.course4.other.ways[match_updates] <- Other_ways_and_degree_role_with_respondent_IDs$online.course4.other.ways
> all$other5.other.ways[match_updates] <- Other_ways_and_degree_role_with_respondent_IDs$other5.other.ways
> all$degree.role[match_updates] <- Other_ways_and_degree_role_with_respondent_IDs$degree.role
Save imputed
data
write.csv(all,"02-descriptive_data/merged_filtered_imputedMedian_likertNumber.csv",row.names = FALSE)
Barplot of likert
variables
all_melt <- melt(all,id.vars = c("Resp.ID","Gender","Age","prof","Context","study.year"),
measure.vars = likert_variables1)
Warning: attributes are not identical across measure variables; they will be dropped
all_melt$value <- factor(all_melt$value,levels=c(1,2,3,4,5),labels=c("Strongly disagree","Disagree","Not sure","Agree","Strongly agree"))
# dim(all_melt)
# 323*length(likert_variables1)
all_melt <- all_melt %>% separate(variable,into=c("item","type"),sep="\\.",remove=FALSE)
Warning: Expected 2 pieces. Missing pieces filled with `NA` in 646 rows [9368, 9369, 9370, 9371, 9372, 9373, 9374, 9375, 9376, 9377, 9378, 9379, 9380, 9381, 9382, 9383, 9384, 9385, 9386, 9387, ...].
ggplot(all_melt,aes(x=variable,fill=value)) + geom_bar(position = "stack",colour="black") +
facet_grid(Context~type,scales = "free")+theme(axis.text.x = element_text(angle = 45, hjust = 1),axis.text=element_text(size=8)) + ggtitle("Filtered dataset") + scale_fill_manual(values=c("#ca0020","#f4a582","#ffffbf","#abd9e9","#2c7bb6","grey"))

filt_sum <- all_melt %>% group_by(Context,variable,type,value) %>% dplyr::summarise(Ngroup=length(value))
`summarise()` has grouped output by 'Context', 'variable', 'type'. You can override using the `.groups` argument.
ggplot(filt_sum,aes(x=value,y=Ngroup,colour=Context,group=interaction(variable, Context))) + geom_line() + geom_point() + facet_wrap(~type,scales = "free")+theme(axis.text.x = element_text(angle = 45, hjust = 1))

Barplot of Educated
and Necessity in the Australian and European Contexts
# add numbers on the bar
educated <- all[all$Context %in% c("German in Australia","Italian in Australia"),]
table(educated$educated1,educated$Context,useNA="always")
German in Australia Italian in Australia <NA>
1 11 9 0
2 25 24 0
3 12 13 0
4 29 18 0
5 11 10 0
<NA> 0 0 0
educated$educated1 <- factor(educated$educated1,levels = c(1,2,3,4,5),labels=c("Strongly disagree","Disagree","Not sure","Agree","Strongly agree"))
tabEdu <- t(table(educated$educated1,educated$Context))
ggdf <- data.frame(Educated = rep(colnames(tabEdu),each=2),
N.Participants = as.numeric(tabEdu),
Context = rep(rownames(tabEdu),times=5))
ggplot(ggdf,aes(x=Educated,y=N.Participants,fill=Context)) + geom_bar(position="dodge",colour="white",stat="identity") + labs(y="N participants") + scale_y_continuous(breaks=seq(0,35,10),limits=c(0,35)) + theme_bw() + ggtitle("Educated by Context")+ geom_text(aes(label = N.Participants), hjust=0.5, vjust=-0.25, size = 2.5,position=position_dodge(width=0.9))

ggplot(ggdf,aes(x=Context,y=N.Participants,fill=Educated)) + geom_bar(position="dodge",colour="white",stat="identity") + labs(y="N participants") + scale_y_continuous(breaks=seq(0,35,10),limits=c(0,35)) + theme_bw() + ggtitle("Educated by Context")+ geom_text(aes(label = N.Participants), hjust=0.5, vjust=-0.25, size = 2.5,position=position_dodge(width=0.9))

# add numbers on the bar
necessity <- all[all$Context %in% c("English in Germany","English in Italy"),]
table(necessity$necessity1,necessity$Context,useNA="always")
English in Germany English in Italy <NA>
1 1 12 0
2 7 16 0
3 13 6 0
4 32 36 0
5 16 20 0
<NA> 1 1 0
necessity$necessity1 <- factor(necessity$necessity1,levels = c(1,2,3,4,5),labels=c("Strongly disagree","Disagree","Not sure","Agree","Strongly agree"))
tabNec <- t(table(necessity$necessity1,necessity$Context,useNA = "always"))[-3,]
ggdf <- data.frame(Necessity = rep(colnames(tabNec),each=2),
N.Participants = as.numeric(tabNec),
Context = rep(rownames(tabNec),times=6))
ggplot(ggdf,aes(x=Necessity,y=N.Participants,fill=Context)) + geom_bar(position="dodge",colour="white",stat="identity") + labs(y="N participants") + scale_y_continuous(breaks=seq(0,40,10),limits=c(0,40)) + theme_bw() + ggtitle("Necessity by Context")+ geom_text(aes(label = N.Participants), hjust=0.5, vjust=-0.25, size = 2.5,position=position_dodge(width=0.9))

ggplot(ggdf,aes(x=Context,y=N.Participants,fill=Necessity)) + geom_bar(position="dodge",colour="white",stat="identity") + labs(y="N participants") + scale_y_continuous(breaks=seq(0,35,10),limits=c(0,35)) + theme_bw() + ggtitle("Necessity by Context")+ geom_text(aes(label = N.Participants), hjust=0.5, vjust=-0.25, size = 2.5,position=position_dodge(width=0.9))

Correlation plot of
items by context
Italian in
Australia
cov <- cor(filtered_conv[filtered_conv$Context == "Italian in Australia",likert_variables1[!(likert_variables1 %in% "necessity1")]],method = "pearson",use="pairwise.complete.obs")
data_cor_ita_in_au <- data.frame(cor_ita_in_au=cov[lower.tri(cov, diag = TRUE)],
var1 = rownames(cov)[unlist(t(mapply(":", 1:nrow(cov), nrow(cov)))[1,])],
var2 = rep(colnames(cov),times=rev(seq(nrow(cov):1))))
row_infos <- data.frame(Variables=sapply(strsplit(colnames(cov),split="\\."),function(x) x[2]))
row_infos$Variables <- as.character(row_infos$Variables)
rownames(row_infos) <- rownames(cov)
row_infos$Variables[which(is.na(row_infos$Variables))] <- c("educated")
row_infos <- row_infos[order(row_infos$Variables),,drop=FALSE]
ann_col_wide <- data.frame(Variable=unique(row_infos$Variables))
ann_colors_wide <- list(Variables=c(comm1="#bd0026",educated="#b35806", id1="#f6e8c3",instru1="#35978f",integr1="#386cb0",intr1="#ffff99",ought1="grey",post1="black",prof1="pink"))
#pheatmap(cov, main = "Italian in Australia",annotation_names_row = FALSE,cluster_cols=TRUE,cluster_rows=TRUE,annotation_col = row_infos[,1,drop=FALSE], annotation_row = row_infos[,1,drop=FALSE], annotation_colors = ann_colors_wide,breaks=seq(-1,1,0.2),col=c("#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"),show_colnames = FALSE,width = 7,height = 7)
###################
diag(cov) <- NA
pheatmap(cov, main = "Italian in Australia",annotation_names_row = FALSE,cluster_cols=TRUE,cluster_rows=TRUE,annotation_col = row_infos[,1,drop=FALSE], annotation_row = row_infos[,1,drop=FALSE]
, annotation_colors = ann_colors_wide,show_colnames = FALSE,breaks = seq(-0.6,0.7,length.out = 50),width = 7,height = 7,color=colorRampPalette(brewer.pal(n = 7, name = "RdBu"))(50))

cov_ItaAus <- cov
German in
Australia
cov <- cor(filtered_conv[filtered_conv$Context == "German in Australia",likert_variables1[!(likert_variables1 %in% "necessity1")]],method = "pearson",use="pairwise.complete.obs")
data_cor_germ_in_au <- data.frame(cor_germ_in_au=cov[lower.tri(cov, diag = TRUE)],
var1 = rownames(cov)[unlist(t(mapply(":", 1:nrow(cov), nrow(cov)))[1,])],
var2 = rep(colnames(cov),times=rev(seq(nrow(cov):1))))
row_infos <- data.frame(Variables=sapply(strsplit(colnames(cov),split="\\."),function(x) x[2]))
row_infos$Variables <- as.character(row_infos$Variables)
rownames(row_infos) <- rownames(cov)
row_infos$Variables[which(is.na(row_infos$Variables))] <- c("educated")
row_infos <- row_infos[order(row_infos$Variables),,drop=FALSE]
ann_col_wide <- data.frame(Variable=unique(row_infos$Variables))
ann_colors_wide <- list(Variables=c(comm1="#bd0026",educated="#b35806", id1="#f6e8c3",instru1="#35978f",integr1="#386cb0",intr1="#ffff99",ought1="grey",post1="black",prof1="pink"))
diag(cov) <- NA
pheatmap(cov, main = "German in Australia",annotation_names_row = FALSE,cluster_cols=TRUE,cluster_rows=TRUE,annotation_col = row_infos[,1,drop=FALSE], annotation_row = row_infos[,1,drop=FALSE]
, annotation_colors = ann_colors_wide,show_colnames = FALSE,breaks = seq(-0.6,0.7,length.out = 50),width = 7,height = 7,color=colorRampPalette(brewer.pal(n = 7, name = "RdBu"))(50))

#
cov_GermAus <- cov
English in
Germany
cov <- cor(filtered_conv[filtered_conv$Context == "English in Germany",likert_variables1[!(likert_variables1 %in% c("reconnect.comm1", "speakersmelb.comm1","comecloser.comm1","educated1"))]],method = "pearson",use="pairwise.complete.obs")
data_cor_eng_in_germ <- data.frame(cor_eng_in_germ=cov[lower.tri(cov, diag = TRUE)],
var1 = rownames(cov)[unlist(t(mapply(":", 1:nrow(cov), nrow(cov)))[1,])],
var2 = rep(colnames(cov),times=rev(seq(nrow(cov):1))))
row_infos <- data.frame(Variables=sapply(strsplit(colnames(cov),split="\\."),function(x) x[2]))
row_infos$Variables <- as.character(row_infos$Variables)
rownames(row_infos) <- rownames(cov)
row_infos$Variables[which(is.na(row_infos$Variables))] <- c("necessity")
row_infos <- row_infos[order(row_infos$Variables),,drop=FALSE]
ann_col_wide <- data.frame(Variable=unique(row_infos$Variables))
ann_colors_wide <- list(Variables=c(id1="#f6e8c3",necessity="#b35806",instru1="#35978f",integr1="#386cb0",intr1="#ffff99",ought1="grey",post1="black",prof1="pink"))
diag(cov) <- NA
pheatmap(cov, main = "English in Germany",annotation_names_row = FALSE,cluster_cols=TRUE,cluster_rows=TRUE,annotation_col = row_infos[,1,drop=FALSE], annotation_row = row_infos[,1,drop=FALSE]
, annotation_colors = ann_colors_wide,show_colnames = FALSE,breaks = seq(-0.6,0.7,length.out = 50),width = 7,height = 7,color=colorRampPalette(brewer.pal(n = 7, name = "RdBu"))(50))

cov_EngGerm <- cov
English in Italy
cov <- cor(filtered_conv[filtered_conv$Context == "English in Italy",likert_variables1[!(likert_variables1 %in% c("reconnect.comm1","speakersmelb.comm1","comecloser.comm1","educated1"))]],method = "pearson",use="pairwise.complete.obs")
data_cor_eng_in_ita <- data.frame(cor_eng_in_ita=cov[lower.tri(cov, diag = TRUE)],
var1 = rownames(cov)[unlist(t(mapply(":", 1:nrow(cov), nrow(cov)))[1,])],
var2 = rep(colnames(cov),times=rev(seq(nrow(cov):1))))
row_infos <- data.frame(Variables=sapply(strsplit(colnames(cov),split="\\."),function(x) x[2]))
row_infos$Variables <- as.character(row_infos$Variables)
rownames(row_infos) <- rownames(cov)
row_infos$Variables[which(is.na(row_infos$Variables))] <- "necessity"
row_infos <- row_infos[order(row_infos$Variables),,drop=FALSE]
ann_col_wide <- data.frame(Variable=unique(row_infos$Variables))
ann_colors_wide <- list(Variables=c(comm1="#bd0026",necessity="#b35806", id1="#f6e8c3",instru1="#35978f",integr1="#386cb0",intr1="#ffff99",ought1="grey",post1="black",prof1="pink"))
diag(cov) <- NA
pheatmap(cov, main = "English in Italy",annotation_names_row = FALSE,cluster_cols=TRUE,cluster_rows=TRUE,annotation_col = row_infos[,1,drop=FALSE], annotation_row = row_infos[,1,drop=FALSE]
, annotation_colors = ann_colors_wide,show_colnames = FALSE,breaks = seq(-0.6,0.7,length.out = 50),width = 7,height = 7,color=colorRampPalette(brewer.pal(n = 7, name = "RdBu"))(50))

#
cov_EngIta <- cov
Correlation between
correlation in the different contexts
We will perform an exploratory FA combining all the contexts
together. This means that we are assuming that the correlation between
items across context has the same direction (does not happen that
cor(item1,item2)_context1 > 0 and cor(item1,item2)_context2 <
0).
common <- rownames(cov_EngIta)[rownames(cov_EngIta) %in% rownames(cov_ItaAus)]
sum(rownames(cov_EngIta) != rownames(cov_EngGerm))
[1] 0
sum(rownames(cov_EngIta) != rownames(cov_GermAus))
Warning: longer object length is not a multiple of shorter object length
[1] 4
sum(rownames(cov_EngIta) != rownames(cov_ItaAus))
Warning: longer object length is not a multiple of shorter object length
[1] 4
sum(rownames(cov_GermAus) != rownames(cov_ItaAus))
[1] 0
common_EngIta <- cov_EngIta[rownames(cov_EngIta) %in% common,colnames(cov_EngIta) %in% common]
common_EngGerm <- cov_EngGerm[rownames(cov_EngGerm) %in% common,colnames(cov_EngGerm) %in% common]
common_GermAus <- cov_GermAus[rownames(cov_GermAus) %in% common,colnames(cov_GermAus) %in% common]
common_ItaAus <- cov_ItaAus[rownames(cov_ItaAus) %in% common,colnames(cov_ItaAus) %in% common]
sum(rownames(common_EngIta) != colnames(common_EngIta))
[1] 0
sum(rownames(common_EngGerm) != colnames(common_EngGerm))
[1] 0
sum(rownames(common_GermAus) != colnames(common_GermAus))
[1] 0
sum(rownames(common_ItaAus) != colnames(common_ItaAus))
[1] 0
par(mfrow=c(2,3))
plot(common_EngIta,common_EngGerm)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")
plot(common_EngIta,common_GermAus)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")
plot(common_EngIta,common_ItaAus)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")
plot(common_EngGerm,common_GermAus)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")
plot(common_EngGerm,common_ItaAus)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")
plot(common_GermAus,common_ItaAus)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")

# Largest differences
low_EngGerm <- lower.tri(common_EngGerm)
common_EngGerm[!low_EngGerm] <- NA
common_GermAus[!(lower.tri(common_GermAus))] <- NA
common_ItaAus[!(lower.tri(common_ItaAus))] <- NA
common_EngIta[!(lower.tri(common_EngIta))] <- NA
mat <- data.frame(common_EngGerm=c(common_EngGerm),
common_EngIta=c(common_EngIta),
common_GermAus = c(common_GermAus),
common_ItaAus = c(common_ItaAus),
compare = paste(rownames(common_EngGerm),colnames(common_EngGerm),sep=".")) %>%
filter(!is.na(common_EngGerm)) %>%
separate(compare,into=c("item1","variable1","item2","variable2"),remove=FALSE,sep="[.]") %>%
unite(group,variable1,variable2,sep=".")
library(ggrepel)
ggplot(mat,aes(x=common_EngGerm,y=common_GermAus,label=compare,colour=group)) + geom_point(alpha=0.5,size=0.8) + geom_text(size=2) +
geom_hline(yintercept=c(0,0.3),linetype="dotted",colour="dark red") +
geom_vline(xintercept=c(0,0.3),linetype="dotted",colour="dark red")

ggplot(mat,aes(x=common_EngGerm,y=common_ItaAus,label=compare,colour=group)) + geom_point(alpha=0.5,size=0.8) + geom_text(size=2) +
geom_hline(yintercept=c(0,0.3),linetype="dotted",colour="dark red") +
geom_vline(xintercept=c(0,0.3),linetype="dotted",colour="dark red")

ggplot(mat,aes(x=common_EngGerm,y=common_EngIta,label=compare,colour=group)) + geom_point(alpha=0.5,size=0.8) + geom_text(size=2) +
geom_hline(yintercept=c(0,0.3),linetype="dotted",colour="dark red") +
geom_vline(xintercept=c(0,0.3),linetype="dotted",colour="dark red")

Different correlation
plot and Pearson’s correlation
cowplot::plot_grid(p1,p2,p3,p4,p5,p6,nrow=3)

knitr::kable(cor_data)
| common_EngGerm-common_ItaAus |
common_EngGerm-common_ItaAus |
0.4538018 |
| common_EngGerm-common_GermAus |
common_EngGerm-common_GermAus |
0.4757044 |
| common_EngIta-common_GermAus |
common_EngIta-common_GermAus |
0.5091050 |
| common_EngIta-common_ItaAus |
common_EngIta-common_ItaAus |
0.5384113 |
| common_EngIta-common_EngGerm |
common_EngIta-common_EngGerm |
0.5957948 |
| common_GermAus-common_ItaAus |
common_GermAus-common_ItaAus |
0.5999612 |
All context
together
cov <- cor(filtered_conv[,likert_variables1],method = "pearson",use="pairwise.complete.obs")
row_infos <- data.frame(Variables=sapply(strsplit(colnames(cov),split="\\."),function(x) x[2]))
row_infos$Variables <- as.character(row_infos$Variables)
rownames(row_infos) <- rownames(cov)
row_infos$Variables[which(is.na(row_infos$Variables))] <- c("necessity","educated")
row_infos <- row_infos[order(row_infos$Variables),,drop=FALSE]
ann_col_wide <- data.frame(Variable=unique(row_infos$Variables))
ann_colors_wide <- list(Variables=c(comm1="#bd0026",educated="orange", id1="#f6e8c3",instru1="#35978f",necessity="#b35806",integr1="#386cb0",intr1="#ffff99",ought1="grey",post1="black",prof1="pink"))
diag(cov) <- NA
pheatmap(cov, main = "All Contexts",annotation_names_row = FALSE,cluster_cols=TRUE,cluster_rows=TRUE,annotation_col = row_infos[,1,drop=FALSE], annotation_row = row_infos[,1,drop=FALSE]
, annotation_colors = ann_colors_wide,show_colnames = FALSE,breaks = seq(-0.6,0.7,length.out = 50),width = 7,height = 7,color=colorRampPalette(brewer.pal(n = 7, name = "RdBu"))(50))

Compare
correlations
library(GGally)
combine_cor <- merge(data_cor_eng_in_ita,data_cor_eng_in_germ,all = TRUE)
combine_cor1 <- merge(combine_cor,data_cor_germ_in_au,all = TRUE)
combine_cor2 <- merge(combine_cor1,data_cor_ita_in_au,all = TRUE)
combine_cor2 <- combine_cor2 %>% separate(var1,into=c("item1","variable1"),sep="[.]",remove=FALSE) %>%
separate(var2,into=c("item2","variable2"),sep="[.]",remove=FALSE) %>%
unite(group,variable1,variable2,sep=".")
Warning: Expected 2 pieces. Missing pieces filled with `NA` in 60 rows [133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, ...].Warning: Expected 2 pieces. Missing pieces filled with `NA` in 5 rows [101, 141, 393, 467, 498].
pairs(combine_cor2[,c("cor_eng_in_ita","cor_eng_in_germ","cor_germ_in_au","cor_ita_in_au")])

ggpairs(combine_cor2[,c("cor_eng_in_ita","cor_eng_in_germ","cor_germ_in_au","cor_ita_in_au")])

Correlation between
correlation in the different contexts
We will perform an exploratory FA combining all the contexts
together. This means that we are assuming that the correlation between
items across context has the same direction (does not happen that
cor(item1,item2)_context1 > 0 and cor(item1,item2)_context2 <
0).
common <- rownames(cov_EngIta)[rownames(cov_EngIta) %in% rownames(cov_ItaAus)]
sum(rownames(cov_EngIta) != rownames(cov_EngGerm))
[1] 0
sum(rownames(cov_EngIta) != rownames(cov_GermAus))
Warning: longer object length is not a multiple of shorter object length
[1] 4
sum(rownames(cov_EngIta) != rownames(cov_ItaAus))
Warning: longer object length is not a multiple of shorter object length
[1] 4
sum(rownames(cov_GermAus) != rownames(cov_ItaAus))
[1] 0
common_EngIta <- cov_EngIta[rownames(cov_EngIta) %in% common,colnames(cov_EngIta) %in% common]
common_EngGerm <- cov_EngGerm[rownames(cov_EngGerm) %in% common,colnames(cov_EngGerm) %in% common]
common_GermAus <- cov_GermAus[rownames(cov_GermAus) %in% common,colnames(cov_GermAus) %in% common]
common_ItaAus <- cov_ItaAus[rownames(cov_ItaAus) %in% common,colnames(cov_ItaAus) %in% common]
sum(rownames(common_EngIta) != colnames(common_EngIta))
[1] 0
sum(rownames(common_EngGerm) != colnames(common_EngGerm))
[1] 0
sum(rownames(common_GermAus) != colnames(common_GermAus))
[1] 0
sum(rownames(common_ItaAus) != colnames(common_ItaAus))
[1] 0
par(mfrow=c(2,3))
plot(common_EngIta,common_EngGerm)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")
plot(common_EngIta,common_GermAus)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")
plot(common_EngIta,common_ItaAus)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")
plot(common_EngGerm,common_GermAus)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")
plot(common_EngGerm,common_ItaAus)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")
plot(common_GermAus,common_ItaAus)
abline(h=c(0,0.3),v=c(0,0.3),lty=2,col = "dark red")
abline(a=0,b=1,lty=2,col = "dark red")

# Largest differences
low_EngGerm <- lower.tri(common_EngGerm)
common_EngGerm[!low_EngGerm] <- NA
common_GermAus[!(lower.tri(common_GermAus))] <- NA
common_ItaAus[!(lower.tri(common_ItaAus))] <- NA
common_EngIta[!(lower.tri(common_EngIta))] <- NA
mat <- data.frame(common_EngGerm=c(common_EngGerm),
common_EngIta=c(common_EngIta),
common_GermAus = c(common_GermAus),
common_ItaAus = c(common_ItaAus),
compare = paste(rownames(common_EngGerm),colnames(common_EngGerm),sep=".")) %>%
filter(!is.na(common_EngGerm)) %>%
separate(compare,into=c("item1","variable1","item2","variable2"),remove=FALSE,sep="[.]") %>%
unite(group,variable1,variable2,sep=".")
library(ggrepel)
ggplot(mat,aes(x=common_EngGerm,y=common_GermAus,label=compare,colour=group)) + geom_point(alpha=0.5,size=0.8) + geom_text(size=2) +
geom_hline(yintercept=c(0,0.3),linetype="dotted",colour="dark red") +
geom_vline(xintercept=c(0,0.3),linetype="dotted",colour="dark red")

ggplot(mat,aes(x=common_EngGerm,y=common_ItaAus,label=compare,colour=group)) + geom_point(alpha=0.5,size=0.8) + geom_text(size=2) +
geom_hline(yintercept=c(0,0.3),linetype="dotted",colour="dark red") +
geom_vline(xintercept=c(0,0.3),linetype="dotted",colour="dark red")

ggplot(mat,aes(x=common_EngGerm,y=common_EngIta,label=compare,colour=group)) + geom_point(alpha=0.5,size=0.8) + geom_text(size=2) +
geom_hline(yintercept=c(0,0.3),linetype="dotted",colour="dark red") +
geom_vline(xintercept=c(0,0.3),linetype="dotted",colour="dark red")

Evaluate internal
consistency of known constructs with alpha
sets <- list(id.var=likert_variables1[grep("\\.id1$",likert_variables1)],
ought.var=likert_variables1[grep("\\.ought1$",likert_variables1)],
intr.var=likert_variables1[grep("\\.intr1$",likert_variables1)],
instru.var=likert_variables1[grep("\\.instru1$",likert_variables1)],
integr1.var=likert_variables1[grep("\\.integr1$",likert_variables1)],
prof.var=likert_variables1[grep("\\.prof1$",likert_variables1)],
post.var=likert_variables1[grep("\\.post1$",likert_variables1)],
comm.var=likert_variables1[grep("\\.comm1$",likert_variables1)])
get_alpha <- function(dataMot,
var=sets$id.var){
var_alpha <- psych::alpha(dataMot[,var])
dataf <- data.frame(alpha=var_alpha$total,
drop = var_alpha$alpha.drop)
rownames(dataf) <- rownames(var_alpha$alpha.drop)
return(dataf)
}
# "Italian in Australia"
ita_in_au_df <- filtered_conv[filtered_conv$Context == "Italian in Australia",]
list_of_ita_in_au <- lapply(sets,function(x) {
get_alpha(dataMot=ita_in_au_df,var=x)})
ita_in_au <- do.call(rbind,list_of_ita_in_au)
ita_in_au$var <- sapply(strsplit(rownames(ita_in_au),split="\\."),function(x) x[1])
ita_in_au$var.full <- sapply(strsplit(rownames(ita_in_au),split="\\."),function(x) x[3])
ita_in_au$Context <- "Italian in Australia"
rownames(ita_in_au) <- NULL
# "German in Australia"
germ_in_au <- do.call(rbind,lapply(sets,function(x) {
get_alpha(dataMot =filtered_conv[filtered_conv$Context == "German in Australia",],
var=x)}))
Warning: Some items were negatively correlated with the total scale and probably
should be reversed.
To do this, run the function again with the 'check.keys=TRUE' option
Some items ( knowledge.instru1 ) were negatively correlated with the total scale and
probably should be reversed.
To do this, run the function again with the 'check.keys=TRUE' option
germ_in_au$var <- sapply(strsplit(rownames(germ_in_au),split="\\."),function(x) x[1])
germ_in_au$var.full <- sapply(strsplit(rownames(germ_in_au),split="\\."),function(x) x[3])
germ_in_au$Context <- "German in Australia"
rownames(germ_in_au) <- NULL
# "English in Germany"
eng_in_germ <- do.call(rbind,lapply(sets[!(names(sets) %in% "comm.var")],function(x) {
get_alpha(dataMot=filtered_conv[filtered_conv$Context == "English in Germany",],
var=x)}))
Warning: Some items were negatively correlated with the total scale and probably
should be reversed.
To do this, run the function again with the 'check.keys=TRUE' option
Some items ( people.ought1 ) were negatively correlated with the total scale and
probably should be reversed.
To do this, run the function again with the 'check.keys=TRUE' option
# the ones that makes issues
get_alpha(dataMot=filtered_conv[filtered_conv$Context == "English in Germany",],
var=sets$ought.var)
Warning: Some items were negatively correlated with the total scale and probably
should be reversed.
To do this, run the function again with the 'check.keys=TRUE' option
Some items ( people.ought1 ) were negatively correlated with the total scale and
probably should be reversed.
To do this, run the function again with the 'check.keys=TRUE' option
eng_in_germ$var <- sapply(strsplit(rownames(eng_in_germ),split="\\."),function(x) x[1])
eng_in_germ$var.full <- sapply(strsplit(rownames(eng_in_germ),split="\\."),function(x) x[3])
eng_in_germ$Context <- "English in Germany"
rownames(eng_in_germ) <- NULL
# "English in Italy"
eng_in_ita <- do.call(rbind,lapply(sets[!(names(sets) %in% "comm.var")],function(x) {
get_alpha(dataMot=filtered_conv[filtered_conv$Context == "English in Italy",],
var=x)}))
eng_in_ita$var <- sapply(strsplit(rownames(eng_in_ita),split="\\."),function(x) x[1])
eng_in_ita$var.full <- sapply(strsplit(rownames(eng_in_ita),split="\\."),function(x) x[3])
eng_in_ita$Context <- "English in Italy"
rownames(eng_in_ita) <- NULL
# combine
full_alpha <- rbind(eng_in_ita,eng_in_germ,germ_in_au,ita_in_au)
full_alpha %>% group_by(Context,var) %>%
summarise(st.alpha = unique(alpha.std.alpha),
G6=unique(alpha.G6.smc.)) %>%
ggplot(.,aes(x=var,y=st.alpha,colour=Context)) + geom_point() + geom_line(aes(group=Context)) + theme_bw()
`summarise()` has grouped output by 'Context'. You can override using the `.groups` argument.

p2=ggplot(full_alpha,aes(x=var.full,y=drop.std.alpha,colour=Context)) + geom_point() + geom_line(aes(group=Context)) + theme_bw() + facet_wrap(~var,scales="free")
Error in ggplot(full_alpha, aes(x = var.full, y = drop.std.alpha, colour = Context)) :
object 'full_alpha' not found
```r
ggplot(full_alpha[full_alpha$var == \instru\,],aes(x=var.full,y=drop.std.alpha,colour=Context)) + geom_point() + geom_line(aes(group=Context)) + theme_bw() + labs(y = \Drop Item - Chronbach's Alpha\, x = \Items\)
```
LS0tCnRpdGxlOiAiQW5hbHlzaXMgb2YgbWVyZ2VkIHF1ZXN0aW9ubmFpcmVzIgphdXRob3I6ICJBbm5hIFF1YWdsaWVyaSAmIFJpY2NhcmRvIEFtb3JhdGkiCmRhdGU6ICIwMy8wOS8yMDE3IgpvdXRwdXQ6CiAgZ2l0aHViX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAnNCcKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCi0tLQoKIyBQbGFuIHRoYXQgSSB3cm90ZSB3aXRoIFJpY2hpJ3MgY29tbWVudHMKCkxpbmsgYXQgaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vZG9jdW1lbnQvZC8xYmROZU9NQVlZOTBrOEZBYlBSV0dCZ1MxWUJFZFAwOWtQMHZjVzB0TmdQYy9lZGl0P3VzcD1zaGFyaW5nCgoKYGBge3IsbWVzc2FnZT1GQUxTRSwgZWNobz1GQUxTRX0KbGlicmFyeShyZWFkcikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocmVzaGFwZTIpCmxpYnJhcnkoY29ycnBsb3QpCmxpYnJhcnkocHN5Y2gpCmxpYnJhcnkocGhlYXRtYXApCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkocGhlYXRtYXApCmxpYnJhcnkoc2pQbG90KQpsaWJyYXJ5KHNqbGFiZWxsZWQpCmxpYnJhcnkoc2ptaXNjKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KHJlYWR4bCkKCmRhdGEoZWZjKQp0aGVtZV9zZXQodGhlbWVfc2pwbG90KCkpCgojIENodW5rIG9wdGlvbnMKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBwcm9tcHQgPSBUUlVFLGNhY2hlID0gVFJVRSxmaWcud2lkdGggPSAxMixmaWcuaGVpZ2h0ID0gMTIpCgpgYGAKCiMgUmVhZCBpbiBkYXRhCgpgYGB7ciBtZXNzYWdlPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CmV1cm9wZWFuIDwtIHJlYWRfY3N2KCIwMS1jbGVhbmluZ19kYXRhX2RhdGEvZXVyb3BlYW5fcmVjb2RlZC5jc3YiKQphdXN0cmFsaWFuIDwtIHJlYWRfY3N2KCIwMS1jbGVhbmluZ19kYXRhX2RhdGEvYXVzdHJhbGlhbl9yZWNvZGVkLmNzdiIpCgpkaW0oZXVyb3BlYW4pCmRpbShhdXN0cmFsaWFuKQoKZXVyb3BlYW4kRVUgPC0gMQphdXN0cmFsaWFuJEFVIDwtIDEKCmFsbCA8LSBtZXJnZShldXJvcGVhbixhdXN0cmFsaWFuLGFsbCA9IFRSVUUpCgp0YWJsZShhbGwkRVUsYWxsJEFVLHVzZU5BID0gImFsd2F5cyIpCmBgYAoKIyMgVmFyaWFibGVzIHRvIGRlc2NyaWJlIGRhdGFzZXQgKGNhbiBiZSBkaWZmZXJlbnQgYmV0d2VlbiBjb250ZXh0cykKCmBgYHtyfQpkZW1vZ3JhcGhpY3NfdmFyIDwtIGMoIkFnZSIsIkdlbmRlciIsIkwxIiwic3BlYWsub3RoZXIuTDIiLCJzdHVkeS5vdGhlci5MMiIsIm9yaWdpbnMiLCJ5ZWFyLnN0dWR5TDIiLCJvdGhlcjUub3RoZXIud2F5cyIsImRlZ3JlZSIsInJvbGVMMi5kZWdyZWUiLCJzdHVkeS55ZWFyIiwicHJvZiIsIkwyLlZDRSIsInVuaTEueWVhciIsIkNvbnRleHQiKQpsMlNjaG9vbCA8LSAiXFwuTDJzY2hvb2wkIgpsMlNjaG9vbF92YXJpYWJsZXMgPC0gY29sbmFtZXMoYWxsKVtncmVwKGwyU2Nob29sLGNvbG5hbWVzKGFsbCkpXQpgYGAKCi0gRmlyc3QgbGFuZ3VhZ2UKCmBgYHtyfQojdGFibGUoYWxsJEwxLGFsbCRDb250ZXh0KSAjIHRvbyBtYW55IGxldmVscyAtIG5lZWRzIHRvIGJlIGNsZWFuZWQgKGV4IHRvdCBudW1iZXIgb2YgbGFuZ3VhZ2VzPykKdGFibGUoYWxsJEwxLHVzZU5BID0gImFsd2F5cyIpCmdncGxvdChhbGwsYWVzKHg9TDEsZmlsbD1Db250ZXh0KSkgKyBnZW9tX2JhcigpICsgY29vcmRfZmxpcCgpICsgZ2d0aXRsZSgiRmlyc3QgTGFuZ3VhZ2UiKSArIGxhYnMoeT0iTi4gb2YgcGFydGljaXBhbnRzIix4PSIiKSt0aGVtZV9idygpCiN0YWJsZShhbGwkc3BlYWsub3RoZXIuTDIsYWxsJENvbnRleHQpCmBgYAoKYGBge3J9CkwyIDwtIGRhdGEuZnJhbWUoRnJlcT10YWJsZShhbGwkc3BlYWsub3RoZXIuTDIpW29yZGVyKHRhYmxlKGFsbCRzcGVhay5vdGhlci5MMiksZGVjcmVhc2luZyA9IFRSVUUpXSwKICAgICAgICAgICAgICAgICBMMj1uYW1lcyh0YWJsZShhbGwkc3BlYWsub3RoZXIuTDIpKVtvcmRlcih0YWJsZShhbGwkc3BlYWsub3RoZXIuTDIpLGRlY3JlYXNpbmcgPSBUUlVFKV0pICMgdG9vIG1hbnkgbGV2ZWxzIC0gbmVlZHMgdG8gYmUgY2xlYW5lZCAoZXggdG90IG51bWJlciBvZiBsYW5ndWFnZXM/KQpoZWFkKEwyKQpgYGAKCi0gb3JpZ2lucwoKYGBge3J9CnRhYmxlKGFsbCRvcmlnaW5zLHVzZU5BID0gImFsd2F5cyIpCmBgYAoKCmBgYHtyfQp0YWJsZShhbGwkeWVhci5zdHVkeUwyKQpgYGAKCmBgYHtyfQp0YWJsZShhbGwkZGVncmVlKQpgYGAKCi0gc3R1ZHkueWVhciBpbiB0aGUgRXVyb3BlYW4gY29udGV4dCBpcyB1bmkxLnllYXIgaW4gdGhlIEF1c3RyYWxpYW4gY29udGV4dAoKYGBge3J9CmFsbCRzdHVkeS55ZWFyW2lzLm5hKGFsbCRzdHVkeS55ZWFyKV0gPC0gYWxsJHVuaTEueWVhcltpcy5uYShhbGwkc3R1ZHkueWVhcildCiN0YWJsZShhbGwkc3R1ZHkueWVhcikKYWxsJHN0dWR5LnllYXIgPC0gaWZlbHNlKGFsbCRzdHVkeS55ZWFyID09ICJBbHJlYWR5IGdyYWR1YXRlZCBhZnRlciA1IHNlbWVzdGVycyBpbiBNYXJjaCAyMDE2LCB3YXMgaW50ZXJlc3RlZCBpbiBzdXJ2ZXJ5L3N0dWR5LCBzb3JyeS4iLCI2dGggc2VtZXN0ZXIiLGFsbCRzdHVkeS55ZWFyKQp0YWJsZShhbGwkc3R1ZHkueWVhcikKYGBgCgotIHByb2ZpY2llbmN5CgpgYGB7cn0KdGFibGUoYWxsJHByb2YsdXNlTkEgPSAiYWx3YXlzIikKYGBgCgojIEZpbHRlciBwYXJ0aWNpcGFudHMgOiBrZWVwIG9ubHkgdGhlIG9uZXMgdGhhdCBtZWV0IHRoZSBpbmNsdXNpb24gY3JpdGVyaWEKCmBgYHtyIEZpbHRlcmVkLGZpZy53aWR0aD0yMCxmaWcuaGVpZ2h0PTE1fQphbGwkc3R1ZHkueWVhcltpcy5uYShhbGwkc3R1ZHkueWVhcildIDwtIGFsbCR1bmkxLnllYXJbaXMubmEoYWxsJHN0dWR5LnllYXIpXQojIEZpbHRlciBvbmx5IHN1YmplY3QgdGhhdCB3ZSB3YW50IHRvIGluY2x1ZGUgaW4gdGhlIHN0dWR5CiMgbmFtZXModGFibGUoYWxsJHN0dWR5LnllYXIpKVsxXSA9IDFzdCBzZW1lc3RlciIKCmZpbHRlcmVkIDwtIHN1YnNldChhbGwsIChzdHVkeS55ZWFyID09ICIxc3QgeWVhciIpIHwgKHN0dWR5LnllYXIgPT0gbmFtZXModGFibGUoYWxsJHN0dWR5LnllYXIpKVsxXSkpCiMmIHllYXIuc3R1ZHlMMiAhPSAiMCB5ZWFycyIKCmBgYAoKCiMjIEltcHV0aW5nIGRlZ3JlZSBiYXNlZCBvbiBRdWFsaXR5IENvbW1lbnRzIHByb3ZpZGVkIGluIHRoZSBxdWVzdGlvbnMKCi0gKio1MzEzOTc2NzE2KiogOiBTQ0kgKHdpc2ggdG8gc3R1ZHkgc2NpZW5jZSBpbiB0aGUgZnV0dXJlKQotICoqNTM1OTg2NjU0NSoqIDogSFVNLlNDSSAoYmFzZWQgb24gZGVncmVlLm90aGVyNykKLSAqKjUzNzUzNzAxMjIqKiA6IFNDSSAoc2hlIHdhbnRzIHRvIGRvIHNjaWVuY2UpCi0gKio1Mzc1Mzc2NzYxKiogOiBIVU0gKHNoZSB3YW50cyB0byBkbyB0cmFuc2xhdGlvbi9yZXNlcmFjaC90ZWFjaGluZykKCmBgYHtyfQpmaWx0ZXJlZCRkZWdyZWVbZmlsdGVyZWQkUmVzcC5JRCAlaW4lICI1MzEzOTc2NzE2Il0gPC0gIlNDSSIKZmlsdGVyZWQkZGVncmVlW2ZpbHRlcmVkJFJlc3AuSUQgJWluJSAiNTM1OTg2NjU0NSJdIDwtICJIVU0uU0NJIgpmaWx0ZXJlZCRkZWdyZWVbZmlsdGVyZWQkUmVzcC5JRCAlaW4lICI1Mzc1MzcwMTIyIl0gPC0gIlNDSSIKZmlsdGVyZWQkZGVncmVlW2ZpbHRlcmVkJFJlc3AuSUQgJWluJSAiNTM3NTM3Njc2MSJdIDwtICJIVU0iCgp0YWJsZShmaWx0ZXJlZCRkZWdyZWUpCmthYmxlKHRhYmxlKGZpbHRlcmVkJENvbnRleHQpKQprYWJsZSh0YWJsZShmaWx0ZXJlZCR5ZWFyLnN0dWR5TDIsZmlsdGVyZWQkQ29udGV4dCkpCmthYmxlKHRhYmxlKGZpbHRlcmVkJHllYXIuc3R1ZHlMMixmaWx0ZXJlZCRwcm9mKSkKa2FibGUodGFibGUoZmlsdGVyZWQkeWVhci5zdHVkeUwyLGZpbHRlcmVkJENvbnRleHQpKQpgYGAKClBlb3BsZSB0aGF0IGhhdmUgc3R1ZGllZCAwIHllYXJzIEwyIGFyZSBqdXN0IGEgc21hbGwgc3Vic2V0IG9mIHRoZSBHZXJtYW4gaW4gQXVzdHJhbGlhIGFuZCBJdGFsaWFuIGluIEF1c3RyYWxpYSBjb250ZXh0IHdoaWNoIG1lYW5zIHRoYXQgYnkgY29ycmVjdGluZyBmb3IgY29udGV4dCB3ZSBhcmUgbm90IHJlbW92aW5nIHRoZSBlZmZlY3Qgb2YgdGhlIDAgeWVhcnMuIEEgd2F5IHRvIHJlbW92ZSB0aGUgZWZmZWN0IG9mIHRoZSAwIHllYXJzIHBhcnRpY2lwYW50cyBhbmQgbm90IGluY2x1ZGluZyB0b28gbWFueSB2YXJpYWJsZXMgY291bGQgYmUgdG8gZXN0aW1hdGUgdGhlIGVmZmVjdCBvZiAwIHllYXJzIHZzIGFsbC4gCgojIERlZmluZSBkZW1vZ3JhcGhpYyB2YXJpYWJsZXMKCiMjIE5lZWQgdG8gY2hlY2sgZGF0YXNldHMgd2l0aCBSY2loaSAod2h5IGRvIHdlIGhhdmUgUUMgaW4gTDE/IEFtIEkgdXNpbmcgbm90IHRoZSBsYXRlc3QgZGF0YXNldD8pCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQphbGwgPC0gZmlsdGVyZWQKZGVtb2dyYXBoaWNzX3ZhciA8LSBjKCJBZ2UiLCJHZW5kZXIiLCJMMSIsInNwZWFrLm90aGVyLkwyIiwic3R1ZHkub3RoZXIuTDIiLCJvcmlnaW5zIiwieWVhci5zdHVkeUwyIiwib3RoZXI1Lm90aGVyLndheXMiLCJkZWdyZWUiLCJyb2xlTDIuZGVncmVlIiwic3R1ZHkueWVhciIsInByb2YiLCJMMi5WQ0UiLCJ1bmkxLnllYXIiLCJDb250ZXh0IikKbDJTY2hvb2wgPC0gIlxcLkwyc2Nob29sJCIKbDJTY2hvb2xfdmFyaWFibGVzIDwtIGNvbG5hbWVzKGFsbClbZ3JlcChsMlNjaG9vbCxjb2xuYW1lcyhhbGwpKV0KCmdncGxvdChhbGwsYWVzKHg9TDEsZmlsbD1Db250ZXh0KSkgKyBnZW9tX2JhcigpICsgY29vcmRfZmxpcCgpICsgZ2d0aXRsZSgiRmlyc3QgTGFuZ3VhZ2UiKSArIGxhYnMoeT0iTi4gb2YgcGFydGljaXBhbnRzIix4PSIiKSArIHRoZW1lX2J3KCkKCnRhYmxlKGFsbCRMMSxhbGwkQ29udGV4dCkKCnRhYmxlKGFsbCRkZWdyZWUsYWxsJEwxKQpgYGAKCi0gQ2hlY2sgZm9yIEwxIGJ1dCB3ZSBkZWNpZGVkIG5vdCB0byBmaWx0ZXIgZm9yIGl0CgpgYGB7cn0KI0ZpbHRlciBieSBMMQoKbmMgPC0gbmFtZXModGFibGUoYWxsJENvbnRleHQpKQp0YWJsZShhbGwkQ29udGV4dCkKbDFfZmlsdGVyIDwtIGFsbFsoYWxsJENvbnRleHQgPT0gbmNbMV0gJiAoYWxsJEwxID09ICJHZXJtYW4iIHwgYWxsJEwxID09ICJHZXJtYW4gYW5kIEVuZ2xpc2giKSkgfCAKICAgICAgICAgICAgICAgICAgICAoYWxsJENvbnRleHQgPT0gbmNbMl0gJiAoYWxsJEwxID09ICJJdGFsaWFuIikpIHwgCiAgICAgICAgICAgICAgICAgICAgKGFsbCRDb250ZXh0ID09IG5jWzNdICYgKGFsbCRMMSA9PSAiRW5nbGlzaCIgfCBhbGwkTDEgPT0gIkVuZ2xpc2ggYW5kIER1dGNoIiB8IGFsbCRMMSA9PSAiR2VybWFuIGFuZCBFbmdsaXNoIikpIHwKICAgICAgICAgICAgICAgICAgICAoYWxsJENvbnRleHQgPT0gbmNbNF0gJiAoYWxsJEwxID09ICJFbmdsaXNoIiB8IGFsbCRMMSA9PSAiRW5nbGlzaCBhbmQgRHV0Y2giIHwgYWxsJEwxID09ICJHZXJtYW4gYW5kIEVuZ2xpc2giKSksXQoKCiNhbGwgPC0gbDFfZmlsdGVyCgojIGRvIG5vdCBmaWx0ZXIgZm9yIEwxCmFsbCA8LSBhbGwKCiMgc3Vic2V0IGRlbW9ncmFwaGljcwpkZW1vIDwtIHN1YnNldChhbGwsc2VsZWN0PWMoIlJlc3AuSUQiLGRlbW9ncmFwaGljc192YXIsbDJTY2hvb2xfdmFyaWFibGVzKSkKCiMgTnVtZXJpIGZpbmFsaQp0YWJsZShsMV9maWx0ZXIkQ29udGV4dCkKdGFibGUoYWxsJENvbnRleHQpCgpgYGAKCi0gRmlsdGVyIG1pc3NpbmcgdmFsdWU6CiAgLSBGaWx0ZXIgcGFydGljaXBhbnRzIHdobyBkaWRuJ3QgcHV0IHRoZSBkZWdyZWUKICAtIHdlIGRvbid0IGNhcmUgYWJvdXQgc3BlYWsub3RoZXIuTDIgYW5kIHN0dWR5Lm90aGVyLkwyCgpgYGB7cn0KbWlzc2luZ19ieVNhbXBsZSA8LSByb3dTdW1zKGlzLm5hKGRlbW8pKQpuYW1lcyhtaXNzaW5nX2J5U2FtcGxlKSA8LSBkZW1vJFJlc3AuSUQKbWlzc2luZ19ieVZhciA8LSBjb2xTdW1zKGlzLm5hKGRlbW8pKQpuYW1lcyhtaXNzaW5nX2J5VmFyKSA8LSBjb2xuYW1lcyhkZW1vKQoKYmFycGxvdChtaXNzaW5nX2J5U2FtcGxlKQpkIDwtIGRhdGEuZnJhbWUobWlzcz1taXNzaW5nX2J5VmFyKQpkJHZhcklEIDwtIHJvd25hbWVzKGQpCmdncGxvdChkYXRhPWQsYWVzKHg9dmFySUQseT1taXNzKSkgKyBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsgdGhlbWVfYncoKSArdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgCgoKZGVtb19taXNzaW5nIDwtIGRlbW8gJT4lIGdyb3VwX2J5KENvbnRleHQpICU+JSBzdW1tYXJpc2Uocm9sZUwyLmRlZ3JlZV9uYSA9IHN1bShpcy5uYShyb2xlTDIuZGVncmVlKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEwyLlZDRV9uYSA9IHN1bShpcy5uYShMMi5WQ0UpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3RoZXI1Lm90aGVyLndheXNfbmE9c3VtKGlzLm5hKG90aGVyNS5vdGhlci53YXlzICkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmkxLnllYXJfbmEgPSBzdW0oaXMubmEodW5pMS55ZWFyKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW1hcnkxLkwyc2Nob29sX25hPXN1bShpcy5uYShwcmltYXJ5MS5MMnNjaG9vbCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDTFMzLkwyc2Nob29sX25hID0gc3VtKGlzLm5hKENMUzMuTDJzY2hvb2wpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVlNMNC5MMnNjaG9vbF9uYT1zdW0oaXMubmEoVlNMNC5MMnNjaG9vbCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWdyZWUgPSBzdW0oaXMubmEoZGVncmVlKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjaG9vTDJjb3VudHJ5NS5MMnNjaG9vbF9uYT1zdW0oaXMubmEoc2Nob29MMmNvdW50cnk1Lkwyc2Nob29sKSkpCgojIFdlIGRvIG5vdCBmaWx0ZXIgZm9yIHNwZWFrLm90aGVyLkwyIG9yIHN0dWR5Lm90aGVyLkwyCgojZGVtb1tpcy5uYShkZW1vJHNwZWFrLm90aGVyLkwyKSxdCiMgdGVuaWFtbwojZGVtb1tpcy5uYShkZW1vJHN0dWR5Lm90aGVyLkwyKSxdCm1pc3NpbmdfYnlTYW1wbGVbbmFtZXMobWlzc2luZ19ieVNhbXBsZSkgPT0gIjUxNjY4NjE1ODEiXQojZGVtb1tpcy5uYShkZW1vJHllYXIuc3R1ZHlMMiksXQptaXNzaW5nX2J5U2FtcGxlW25hbWVzKG1pc3NpbmdfYnlTYW1wbGUpID09ICI1Mzc4Nzk4Nzg3Il0KCiMgcmVtb3ZlIE5BIGZyb20gZGVncmVlCiN0YWJsZShkZW1vJGRlZ3JlZSx1c2VOQSA9ICJhbHdheXMiKQojIFJlbW92ZSBwZW9wbGUKYWxsIDwtIGFsbFshaXMubmEoYWxsJGRlZ3JlZSksXQpgYGAKCiMjIFN0YXRzIGFib3V0IGZpbHRlcmVkIGRhdGFzZXQKCmBgYHtyfQprYWJsZSh0YWJsZShhbGwkQ29udGV4dCkpCmthYmxlKHRhYmxlKGFsbCRzdHVkeS55ZWFyKSkKa2FibGUodGFibGUoYWxsJHllYXIuc3R1ZHlMMikpCmBgYAoKIyMgUmVjb2RlZCBkZW1vZ3JhcGhpYyB2YXJpYWJsZXMKCmBgYHtyfQpyZWNvZGVkX2RlbV9yaWNoaSA8LSByZWFkX2V4Y2VsKCIwMi1kZXNjcmlwdGl2ZV9kYXRhLzIxIDAzIG1lcmdlZF9maWx0ZXJlZF9pbXB1dGVkTWVkaWFuX2xpa2VydE51bWJlci54bHN4IikKYGBgCgoKIyMgV3JpdGUgZmlsdGVyZWQgYW5kIG1lcmdlZCBkYXRhc2V0CgpgYGB7cn0Kd3JpdGUuY3N2KGFsbCxmaWxlLnBhdGgoIjAyLWRlc2NyaXB0aXZlX2RhdGEvY29udGV4dC1tZXJnZWRfZmlsdGVyZWQuY3N2IikpCmBgYAoKIyMgRGVzY3JpcHRpdmUgcGxvdHMgYW5kIHRhYmxlcwoKYGBge3Igc3BlYWsub3RoZXIuTDJfYmluYXJ5LG1lc3NhZ2U9RkFMU0V9CmFsbCRzcGVhay5vdGhlci5MMl9iaW5hcnkgPC0gaWZlbHNlKCFpcy5uYShhbGwkc3BlYWsub3RoZXIuTDIpICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIShhbGwkc3BlYWsub3RoZXIuTDIgJWluJSBjKCJZZXMiLCJObyIpKSwiWWVzIixhcy5jaGFyYWN0ZXIoYWxsJHNwZWFrLm90aGVyLkwyKSkKCgprYWJsZSh0YWJsZShhbGwkc3BlYWsub3RoZXIuTDJfYmluYXJ5LGFsbCRDb250ZXh0LHVzZU5BID0gImFsd2F5cyIpKQoKYGBgCgotIEFnZQoKYGBge3IgYWdlX2J5X2NvbnRleHQsbWVzc2FnZT1GQUxTRX0KdGFiQWdlIDwtIHQodGFibGUoYWxsJEFnZSxhbGwkQ29udGV4dCkpCmdnZGYgPC0gZGF0YS5mcmFtZShBZ2UgPSByZXAoY29sbmFtZXModGFiQWdlKSxlYWNoPTQpWyEoYXMubnVtZXJpYyh0YWJBZ2UpID09IDApXSwKICBOLlBhcnRpY2lwYW50cyA9IGFzLm51bWVyaWModGFiQWdlKVshKGFzLm51bWVyaWModGFiQWdlKSA9PSAwKV0sCiAgQ29udGV4dCA9IHJlcChyb3duYW1lcyh0YWJBZ2UpLHRpbWVzPTMpWyEoYXMubnVtZXJpYyh0YWJBZ2UpID09IDApXSkKCmdncGxvdChnZ2RmLGFlcyh4PUFnZSx5PU4uUGFydGljaXBhbnRzLGZpbGw9Q29udGV4dCkpICsgZ2VvbV9iYXIocG9zaXRpb249ImRvZGdlIixjb2xvdXI9IndoaXRlIixzdGF0PSJpZGVudGl0eSIpICArIHNjYWxlX3lfY29udGludW91cyhicmVha3M9c2VxKDAsOTAsMTApLGxpbWl0cz1jKDAsOTApKSArIHRoZW1lX2J3KCkgKyBnZ3RpdGxlKCJQYXJ0aWNpcGFudHMgYnkgYWdlIikrCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IE4uUGFydGljaXBhbnRzKSwgaGp1c3Q9MC41LCB2anVzdD0tMC4yNSwgc2l6ZSA9IDIuNSxwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjkpKSAKCmBgYAoKYGBge3IgZ2VuZGVyX2J5X2NvbnRleHQsbWVzc2FnZT1GQUxTRX0KIyBhZGQgbnVtYmVycyBvbiB0aGUgYmFyCgp0YWJBZ2UgPC0gdCh0YWJsZShhbGwkR2VuZGVyLGFsbCRDb250ZXh0KSkKZ2dkZiA8LSBkYXRhLmZyYW1lKEdlbmRlciA9IHJlcChjb2xuYW1lcyh0YWJBZ2UpLGVhY2g9NClbIShhcy5udW1lcmljKHRhYkFnZSkgPT0gMCldLAogIE4uUGFydGljaXBhbnRzID0gYXMubnVtZXJpYyh0YWJBZ2UpWyEoYXMubnVtZXJpYyh0YWJBZ2UpID09IDApXSwKICBDb250ZXh0ID0gcmVwKHJvd25hbWVzKHRhYkFnZSksdGltZXM9MylbIShhcy5udW1lcmljKHRhYkFnZSkgPT0gMCldKQoKCmdncGxvdChnZ2RmLGFlcyh4PUdlbmRlcix5PU4uUGFydGljaXBhbnRzLGZpbGw9Q29udGV4dCkpICsgZ2VvbV9iYXIocG9zaXRpb249ImRvZGdlIixjb2xvdXI9IndoaXRlIixzdGF0PSJpZGVudGl0eSIpICArIGxhYnMoeT0iTiBwYXJ0aWNpcGFudHMiKSArIHNjYWxlX3lfY29udGludW91cyhicmVha3M9c2VxKDAsOTAsMTApLGxpbWl0cz1jKDAsOTApKSArIHRoZW1lX2J3KCkgKyBnZ3RpdGxlKCJQYXJ0aWNpcGFudHMgYnkgZ2VuZGVyIikrICBnZW9tX3RleHQoYWVzKGxhYmVsID0gTi5QYXJ0aWNpcGFudHMpLCBoanVzdD0wLjUsIHZqdXN0PS0wLjI1LCBzaXplID0gMi41LHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuOSkpIAoKYGBgCgpgYGB7ciBvcmlnbnNfYnlfY29udGV4dCxtZXNzYWdlPUZBTFNFfQojIGFkZCBudW1iZXJzIG9uIHRoZSBiYXIKdGFiQWdlIDwtIHQodGFibGUoYWxsJG9yaWdpbnMsYWxsJENvbnRleHQpKQpnZ3Bsb3QoYWxsLGFlcyh4PW9yaWdpbnMsZmlsbD1Db250ZXh0KSkgKyBnZW9tX2Jhcihwb3NpdGlvbj0iZG9kZ2UiLGNvbG91cj0id2hpdGUiKSArIGdndGl0bGUoIk9yaWdpbnMgYnkgY29udGV4dCIpICsgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1zZXEoMCw5MCwxMCksbGltaXRzPWMoMCw5MCkpICsgdGhlbWVfYncoKSArIGRyYXdfZ3JvYih0YWJsZUdyb2IodGFiQWdlKSwgeD0yLCB5PTYwLCB3aWR0aD0wLjMsIGhlaWdodD0wLjQpICsgZ2d0aXRsZSgiUGFydGljaXBhbnRzIGJ5IG9yaWdpbnMiKQp0YWJBZ2UKYGBgCgotIHByb2ZpY2llbmN5CgpgYGB7ciBwcm9maWNpZW5jeV9ieV9jb250ZXh0LG1lc3NhZ2U9RkFMU0V9CnRhYkFnZSA8LSB0KHRhYmxlKGFsbCRwcm9mLGFsbCRDb250ZXh0KSkKZ2dwbG90KGFsbCxhZXMoeD1Db250ZXh0LGZpbGw9cHJvZikpICsgZ2VvbV9iYXIocG9zaXRpb249ImRvZGdlIixjb2xvdXI9IndoaXRlIikgKyBnZ3RpdGxlKCJQcm9maWNpZW5jeSBieSBjb250ZXh0IikgKyBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDkwLDEwKSxsaW1pdHM9YygwLDkwKSkgKyB0aGVtZV9idygpICsgZHJhd19ncm9iKHRhYmxlR3JvYih0YWJBZ2UpLCB4PTIsIHk9ODAsIHdpZHRoPTAuMywgaGVpZ2h0PTAuNCkKdGFiQWdlCmBgYAoKLSBMMi5WQ0UKCmBgYHtyIEwyVkNFX2J5X2NvbnRleHQsbWVzc2FnZT1GQUxTRX0KdGFiQWdlIDwtIHQodGFibGUoYWxsW2FsbCRDb250ZXh0ICE9ICJFbmdsaXNoIGluIEdlcm1hbnkiICYgYWxsJENvbnRleHQgIT0gIkVuZ2xpc2ggaW4gSXRhbHkiLCJMMi5WQ0UiXSxhbGxbYWxsJENvbnRleHQgIT0gIkVuZ2xpc2ggaW4gR2VybWFueSIgJiBhbGwkQ29udGV4dCAhPSAiRW5nbGlzaCBpbiBJdGFseSIsJ0NvbnRleHQnXSx1c2VOQSA9ICJhbHdheXMiKSkKdGFiQWdlIDwtIHRhYkFnZVstMyxdCgpnZ3Bsb3QoYWxsW2FsbCRDb250ZXh0ICE9ICJFbmdsaXNoIGluIEdlcm1hbnkiICYgYWxsJENvbnRleHQgIT0gIkVuZ2xpc2ggaW4gSXRhbHkiLF0sYWVzKHg9Q29udGV4dCxmaWxsPUwyLlZDRSkpICsgZ2VvbV9iYXIocG9zaXRpb249ImRvZGdlIixjb2xvdXI9IndoaXRlIikgKyBnZ3RpdGxlKCJMMi5WQ0UgYnkgY29udGV4dCIpICsgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1zZXEoMCw5MCwxMCksbGltaXRzPWMoMCw5MCkpICsgdGhlbWVfYncoKSArIGRyYXdfZ3JvYih0YWJsZUdyb2IodGFiQWdlKSwgeD0yLCB5PTgwLCB3aWR0aD0wLjMsIGhlaWdodD0wLjQpCmBgYAoKLSBkYSBtZXR0ZXJlIGEgcG9zdG8gY29uIFJpY2hpCgpgYGB7ciB5ZWFyLnN0dWR5TDJfRXVyb3BlYW5fY29udGV4dCxtZXNzYWdlPUZBTFNFfQojIHllYXIgc3R1ZHkgTDIKdGFibGUoYWxsJHllYXIuc3R1ZHlMMixhbGwkb3RoZXIueWVhci5zdHVkeUwyLnJpY2hpKQoKYWxsJHllYXIuc3R1ZHlMMiA8LSBpZmVsc2UoYWxsJHllYXIuc3R1ZHlMMiA9PSAiT3RoZXIiLGFsbCRvdGhlci55ZWFyLnN0dWR5TDIucmljaGksYWxsJHllYXIuc3R1ZHlMMiApCgojIEV1cm9wZWFuIGNvbnRleHQKZ2dwbG90KGFsbFthbGwkQ29udGV4dCA9PSAiRW5nbGlzaCBpbiBHZXJtYW55IiB8IGFsbCRDb250ZXh0ID09ICJFbmdsaXNoIGluIEl0YWx5IixdLGFlcyh4PWRlZ3JlZSxmaWxsPXllYXIuc3R1ZHlMMikpICsgZ2VvbV9iYXIocG9zaXRpb249ImRvZGdlIixjb2xvdXI9IndoaXRlIikgKyB0aGVtZV9idygpICsgZ2d0aXRsZSgiRGVncmVlIGJ5IHN0dWR5IHllYXIgTDIsIGJ5IENvbnRleHQiKSArICBmYWNldF9ncmlkKH5Db250ZXh0LHNjYWxlcz0iZnJlZSIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKyBsYWJzKHkgPSAiTiBwYXJ0aWNpcGFudHMiLCB4ID0gImRlZ3JlZSIpCmBgYAoKLSBEZWdyZWUgb2YgZW5yb2xtZW50CgpgYGB7ciBkZWdyZWVfYnlfY29udGV4dCxtZXNzYWdlPUZBTFNFfQojIEF1c3RyYWxpYW4gY29udGV4dAp0YWJBZ2UgPC0gdCh0YWJsZShhbGxbYWxsJENvbnRleHQgPT0gIkl0YWxpYW4gaW4gQXVzdHJhbGlhIiB8IGFsbCRDb250ZXh0ID09ICJHZXJtYW4gaW4gQXVzdHJhbGlhIiwnZGVncmVlJ10sYWxsW2FsbCRDb250ZXh0ID09ICJJdGFsaWFuIGluIEF1c3RyYWxpYSIgfCBhbGwkQ29udGV4dCA9PSAiR2VybWFuIGluIEF1c3RyYWxpYSIsJ0NvbnRleHQnXSkpCmdncGxvdChhbGxbYWxsJENvbnRleHQgPT0gIkl0YWxpYW4gaW4gQXVzdHJhbGlhIiB8IGFsbCRDb250ZXh0ID09ICJHZXJtYW4gaW4gQXVzdHJhbGlhIixdLGFlcyh4PUNvbnRleHQsZmlsbD1kZWdyZWUpKSArIGdlb21fYmFyKHBvc2l0aW9uPSJkb2RnZSIsY29sb3VyPSJ3aGl0ZSIpICsgdGhlbWVfYncoKSArIGdndGl0bGUoIkRlZ3JlZSBpbiBBdXN0cmFsaWFuIENvbnRleHRzIikgKyBkcmF3X2dyb2IodGFibGVHcm9iKHRhYkFnZSksIHg9MS4sIHk9NDAsIHdpZHRoPTAuMywgaGVpZ2h0PTAuNCkKdGFiQWdlCmBgYAoKYGBge3IgeWVhci5zdHVkeUwyX0F1c3RyYWxpYW5fY29udGV4dCxtZXNzYWdlPUZBTFNFfQojIEF1c3RyYWxpYW4gY29udGV4dAp0YWJBZ2UgPC0gdCh0YWJsZShhbGxbYWxsJENvbnRleHQgPT0gIkVuZ2xpc2ggaW4gSXRhbHkiIHwgYWxsJENvbnRleHQgPT0gIkVuZ2xpc2ggaW4gR2VybWFueSIsJ2RlZ3JlZSddLGFsbFthbGwkQ29udGV4dCA9PSAiRW5nbGlzaCBpbiBJdGFseSIgfCBhbGwkQ29udGV4dCA9PSAiRW5nbGlzaCBpbiBHZXJtYW55IiwnQ29udGV4dCddKSkKCmdncGxvdChhbGxbYWxsJENvbnRleHQgPT0gIkVuZ2xpc2ggaW4gSXRhbHkiIHwgYWxsJENvbnRleHQgPT0gIkVuZ2xpc2ggaW4gR2VybWFueSIsXSxhZXMoeD1Db250ZXh0LGZpbGw9ZGVncmVlKSkgKyBnZW9tX2Jhcihwb3NpdGlvbj0iZG9kZ2UiLGNvbG91cj0id2hpdGUiKSArIHRoZW1lX2J3KCkgKyBnZ3RpdGxlKCJEZWdyZWUgaW4gRXVyb3BlYW4gQ29udGV4dHMiKQoKdGFiQWdlCmBgYAoKCiMgQXVzdHJhbGlhbiBjb250ZXh0IHNwY2lmaWMgdmFyaWFibGVzIAoKYGBge3J9CmthYmxlKHRhYmxlKGFsbCRyZWNvbm5lY3QuY29tbSxhbGwkQ29udGV4dCkpCmthYmxlKHRhYmxlKGFsbCRzcGVha2Vyc21lbGIuY29tbSxhbGwkQ29udGV4dCkpCmthYmxlKHRhYmxlKGFsbCRjb21lY2xvc2VyLmNvbW0sYWxsJENvbnRleHQpKQpgYGAKCgpcY2xlYXJwYWdlCgojIExpa2VydCBzY2FsZXMKCmBgYHtyIGluY2x1ZGU9RkFMU0UsbWVzc2FnZT1GQUxTRX0KbGlrZXJ0X2dyZXAgPC0gIlxcLmlkJHxcXC5vdWdodCR8XFwuaW50ciR8XFwuaW5zdHJ1JHxcXC5pbnRlZ3IkfFxcLnByb2YkfFxcLnBvc3QkfFxcLmNvbW0kfF5uZWNlc3NpdHkkfF5lZHVjYXRlZCQiCgojIGFsbApsaWtlcnRfdmFyaWFibGVzX2FsbCA8LSBjb2xuYW1lcyhhbGwpW2dyZXAobGlrZXJ0X2dyZXAsY29sbmFtZXMoYWxsKSldCmxpa2VydF92YXJpYWJsZXNfYWxsCmxpa2VydF92YXJpYWJsZXNfYWxsIDwtIGxpa2VydF92YXJpYWJsZXNfYWxsWyEobGlrZXJ0X3ZhcmlhYmxlc19hbGwgJWluJSAib3RoZXIucHJvZiIpXQoKYGBgCgotICoqQ29udmVydCBMaWtlcnQgc2NhbGVzIHRvIG51bWJlcnMqKgoKYGBge3IgZmlnLndpZHRoPTE1LGZpZy5oZWlnaHQ9MTV9Cgpjb252ZXJ0VG9OdW1iZXIgPC0gZnVuY3Rpb24oY29sdW1uKXsKICBjb2x1bW4gPC0gZmFjdG9yKGNvbHVtbixsZXZlbHMgPSBjKCJTdHJvbmdseSBkaXNhZ3JlZSIsIkRpc2FncmVlIiwiTm90IHN1cmUiLCJBZ3JlZSIsIlN0cm9uZ2x5IGFncmVlIikpCiAgY29sdW1uX251bWJlciA8LSBhcy5udW1lcmljKGNvbHVtbikKICByZXR1cm4oY29sdW1uX251bWJlcikKfQoKdGFibGUoYWxsJENvbnRleHQpCnRhYmxlKGFsbCRzdHVkeS55ZWFyKQoKY29udmVydF9saWtlcnQgPC0gZGF0YS5mcmFtZShhcHBseShzdWJzZXQoYWxsLHNlbGVjdD1saWtlcnRfdmFyaWFibGVzX2FsbCksMixjb252ZXJ0VG9OdW1iZXIpKQpjb2xuYW1lcyhjb252ZXJ0X2xpa2VydCkgPC0gcGFzdGUwKGNvbG5hbWVzKGNvbnZlcnRfbGlrZXJ0KSwiMSIpCgpsaWtlcnRfdmFyaWFibGVzMSA8LSBwYXN0ZTAobGlrZXJ0X3ZhcmlhYmxlc19hbGwsIjEiKQoKIyBqb2luIHRoZSBjb252ZXJ0ZWQgdmFyaWFibGVzIHRvIHRoZSBmaWx0ZXJlZCBkYXRhc2V0CmZpbHRlcmVkX2NvbnYgPC0gY2JpbmQoYWxsLGNvbnZlcnRfbGlrZXJ0KQoKdGFibGUoZmlsdGVyZWRfY29udlssbGlrZXJ0X3ZhcmlhYmxlc19hbGxbNF1dLGZpbHRlcmVkX2NvbnZbLGxpa2VydF92YXJpYWJsZXMxWzRdXSx1c2VOQSA9ICJhbHdheXMiKQoKd3JpdGUuY3N2KGZpbHRlcmVkX2NvbnYsIjAyLWRlc2NyaXB0aXZlX2RhdGEvbWVyZ2VkX2ZpbHRlcmVkX2xpa2VydE51bWJlci5jc3YiLHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMjIEltcHV0ZSBtaXNzaW5nIHZhbHVlcyAtIFVzaW5nIG1lZGlhbiB2YWx1ZXMKClRoZSBtaXNzaW5nIHZhbHVlcyBhcHBlYXJzIHRvIGJlIGF0IHJhbmRvbSBhbmQgdGhlcmUgYXJlIG1heCB0d28gbWlzc2luZyB2YWx1ZXMgaW4gb25lIHZhcmlhYmxlIChzZWUgcGxvdHMgYmVsb3cpLiBJbiBvcmRlciBub3QgdG8gbG9vc2UgMTIgcGFydGljaXBhbnRzIHdoaWxlIGRvaW5nIHRoZSBmYWN0b3IgYW5hbHlzaXMgYWNyb3NzIGNvbnRleHRzIGl0IGlzIHByZWZlcmFibGUgdG8gaW1wdXRlIHRoZSAxMiBtaXNzaW5nIHZhbHVlcy4gCgpgYGB7cn0KYWxsIDwtIGZpbHRlcmVkX2NvbnYKCiMgSXRlbXMgdG8gdXNlIGZvciBmYWN0b3IgYW5hbHlzaXMgOiBpdGVtcyBzaGFyZWQgYmV0d2VlbiBjb250ZXh0cwojIGl0ZW1zIHRvIGJlIHVzZWQgZm9yIHRoZSBGQQoKdXNhYmxlX2l0ZW1zIDwtIGxpa2VydF92YXJpYWJsZXMxWyEobGlrZXJ0X3ZhcmlhYmxlczEgJWluJSBjKCJuZWNlc3NpdHkxIiwiZWR1Y2F0ZWQxIiwicmVjb25uZWN0LmNvbW0xIiwgInNwZWFrZXJzbWVsYi5jb21tMSIsICJjb21lY2xvc2VyLmNvbW0xIikpXQpgYGAKCgpgYGB7cn0Kcm93bmFtZXMoYWxsKSA8LSBhbGwkUmVzcC5JRAp1c2FibGVfZGF0YV9jb250ZXh0IDwtIGFsbFssYyh1c2FibGVfaXRlbXMsIkNvbnRleHQiKV0KZGF0X25vTkEgPC0gdXNhYmxlX2RhdGFfY29udGV4dFtyb3dTdW1zKGlzLm5hKHVzYWJsZV9kYXRhX2NvbnRleHQpKSA9PSAwLF0KYWxsX25vTkEgPC0gYWxsW3Jvd1N1bXMoaXMubmEodXNhYmxlX2RhdGFfY29udGV4dCkpID09IDAsXQp0YWJsZShyb3dTdW1zKGlzLm5hKHVzYWJsZV9kYXRhX2NvbnRleHQpKSkKIyBQYXJ0aWNpcGFudHMgd2l0aCBOQSB0byByZW1vdmUKdGFibGUocm93U3Vtcyhpcy5uYSh1c2FibGVfZGF0YV9jb250ZXh0KSksdXNhYmxlX2RhdGFfY29udGV4dCRDb250ZXh0LHVzZU5BID0gImFsd2F5cyIpCgojIFZhcmlhYmxlIG1pc3NpbmcgdmFsdWVzCnRhYmxlKGNvbFN1bXMoaXMubmEodXNhYmxlX2RhdGFfY29udGV4dCkpKQp0YWJsZShyb3dTdW1zKGlzLm5hKHVzYWJsZV9kYXRhX2NvbnRleHQpKSx1c2FibGVfZGF0YV9jb250ZXh0JENvbnRleHQsdXNlTkEgPSAiYWx3YXlzIikKCiMgY2hlY2sgd2hhdCB0byB1c2UgdG8gaW1wdXRlCiMgaGF2ZSBhIGxvb2sgYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBtaXNzaW5nIHZhbHVlcwpsaWJyYXJ5KG1pY2UpCmxpYnJhcnkoVklNKQoKbWljZV9wbG90IDwtIGFnZ3IodXNhYmxlX2RhdGFfY29udGV4dFssdXNhYmxlX2l0ZW1zXSwgY29sPWMoJ25hdnlibHVlJywneWVsbG93JyksCiAgICAgICAgICAgICAgICAgICAgbnVtYmVycz1UUlVFLCBzb3J0VmFycz1UUlVFLAogICAgICAgICAgICAgICAgICAgIGxhYmVscz1uYW1lcyh1c2FibGVfZGF0YV9jb250ZXh0Wyx1c2FibGVfaXRlbXNdKSwgY2V4LmF4aXM9LjQsCiAgICAgICAgICAgICAgICAgICAgZ2FwPTEsIHlsYWI9YygiTWlzc2luZyBkYXRhIiwiUGF0dGVybiIpLGNleC5udW1iZXJzPTAuNSkKCiMgSW1wdXRpbmcgdXNpbmcgbWVkaWFuCmxpYnJhcnkoSG1pc2MpCmltcHV0ZWRNZWRpYW4gPC0gdXNhYmxlX2RhdGFfY29udGV4dAoKaW1wdXRlZE1lZGlhbiRnbG9iYWxhY2Nlc3MucG9zdDEgPC0gd2l0aChpbXB1dGVkTWVkaWFuWyx1c2FibGVfaXRlbXNdLCBpbXB1dGUoZ2xvYmFsYWNjZXNzLnBvc3QxLCBtZWRpYW4pKQppbXB1dGVkTWVkaWFuJGNpdGl6ZW4ucG9zdDEgPC0gd2l0aChpbXB1dGVkTWVkaWFuWyx1c2FibGVfaXRlbXNdLCBpbXB1dGUoY2l0aXplbi5wb3N0MSwgbWVkaWFuKSkKaW1wdXRlZE1lZGlhbiRtb25leS5pbnN0cnUxIDwtIHdpdGgoaW1wdXRlZE1lZGlhblssdXNhYmxlX2l0ZW1zXSwgaW1wdXRlKG1vbmV5Lmluc3RydTEsIG1lZGlhbikpCmltcHV0ZWRNZWRpYW4ka25vd2xlZGdlLmluc3RydTEgPC0gd2l0aChpbXB1dGVkTWVkaWFuWyx1c2FibGVfaXRlbXNdLCBpbXB1dGUoa25vd2xlZGdlLmluc3RydTEsIG1lZGlhbikpCmltcHV0ZWRNZWRpYW4kbGlmZS5pbnRyMSA8LSB3aXRoKGltcHV0ZWRNZWRpYW5bLHVzYWJsZV9pdGVtc10sIGltcHV0ZShsaWZlLmludHIxLCBtZWRpYW4pKQppbXB1dGVkTWVkaWFuJHRpbWUuaW50ZWdyMSA8LSB3aXRoKGltcHV0ZWRNZWRpYW5bLHVzYWJsZV9pdGVtc10sIGltcHV0ZSh0aW1lLmludGVncjEsIG1lZGlhbikpCmltcHV0ZWRNZWRpYW4kZXhwZWN0Lm91Z2h0MSA8LSB3aXRoKGltcHV0ZWRNZWRpYW5bLHVzYWJsZV9pdGVtc10sIGltcHV0ZShleHBlY3Qub3VnaHQxLCBtZWRpYW4pKQppbXB1dGVkTWVkaWFuJGpvYi5pbnN0cnUxIDwtIHdpdGgoaW1wdXRlZE1lZGlhblssdXNhYmxlX2l0ZW1zXSwgaW1wdXRlKGpvYi5pbnN0cnUxLCBtZWRpYW4pKQppbXB1dGVkTWVkaWFuJGNhcmVlci5pbnN0cnUxIDwtIHdpdGgoaW1wdXRlZE1lZGlhblssdXNhYmxlX2l0ZW1zXSwgaW1wdXRlKGNhcmVlci5pbnN0cnUxLCBtZWRpYW4pKQppbXB1dGVkTWVkaWFuJG1lZXRpbmcuaW50ZWdyMSA8LSB3aXRoKGltcHV0ZWRNZWRpYW5bLHVzYWJsZV9pdGVtc10sIGltcHV0ZShtZWV0aW5nLmludGVncjEsIG1lZGlhbikpCmltcHV0ZWRNZWRpYW4kaW50ZXJhY3QucG9zdDEgPC0gd2l0aChpbXB1dGVkTWVkaWFuWyx1c2FibGVfaXRlbXNdLCBpbXB1dGUoaW50ZXJhY3QucG9zdDEsIG1lZGlhbikpCgojIGNoZWNrIGJlZm9yZSBhZnRlcgp0YWJsZShpbXB1dGVkTWVkaWFuJHRpbWUuaW50ZWdyMSkKdGFibGUodXNhYmxlX2RhdGFfY29udGV4dCR0aW1lLmludGVncjEpCgp0YWJsZShpbXB1dGVkTWVkaWFuJGxpZmUuaW50cjEpCnRhYmxlKHVzYWJsZV9kYXRhX2NvbnRleHQkbGlmZS5pbnRyMSkKCnRhYmxlKGltcHV0ZWRNZWRpYW4ka25vd2xlZGdlLmluc3RydTEpCnRhYmxlKHVzYWJsZV9kYXRhX2NvbnRleHQka25vd2xlZGdlLmluc3RydTEpCgp0YWJsZShpbXB1dGVkTWVkaWFuJG1vbmV5Lmluc3RydTEpCnRhYmxlKHVzYWJsZV9kYXRhX2NvbnRleHQkbW9uZXkuaW5zdHJ1MSkKCnRhYmxlKGltcHV0ZWRNZWRpYW4kY2l0aXplbi5wb3N0MSkKdGFibGUodXNhYmxlX2RhdGFfY29udGV4dCRjaXRpemVuLnBvc3QxKQoKdGFibGUoaW1wdXRlZE1lZGlhbiRnbG9iYWxhY2Nlc3MucG9zdDEpCnRhYmxlKHVzYWJsZV9kYXRhX2NvbnRleHQkZ2xvYmFsYWNjZXNzLnBvc3QxKQoKCnRhYmxlKGltcHV0ZWRNZWRpYW4kZXhwZWN0Lm91Z2h0MSkKdGFibGUodXNhYmxlX2RhdGFfY29udGV4dCRleHBlY3Qub3VnaHQxKQoKdGFibGUoaW1wdXRlZE1lZGlhbiRqb2IuaW5zdHJ1MSkKdGFibGUodXNhYmxlX2RhdGFfY29udGV4dCRqb2IuaW5zdHJ1MSkKCnRhYmxlKGltcHV0ZWRNZWRpYW4kY2FyZWVyLmluc3RydTEpCnRhYmxlKHVzYWJsZV9kYXRhX2NvbnRleHQkY2FyZWVyLmluc3RydTEpCgp0YWJsZShpbXB1dGVkTWVkaWFuJG1lZXRpbmcuaW50ZWdyMSkKdGFibGUodXNhYmxlX2RhdGFfY29udGV4dCRtZWV0aW5nLmludGVncjEpCgp0YWJsZShpbXB1dGVkTWVkaWFuJGludGVyYWN0LnBvc3QxKQp0YWJsZSh1c2FibGVfZGF0YV9jb250ZXh0JGludGVyYWN0LnBvc3QxKQoKCmBgYAoKLSBTdWJzdGl0dXRlIGltcHV0ZWQgZGF0YSBmb3IgdGhlIGNvbW1vbiB2YXJpYWJsZXMgdG8gYmUgdXNlZCBpbiB0aGUgRmFjdG9yIEFuYWx5c2lzCgpgYGB7cn0KYWxsIDwtIGFsbFssIShjb2xuYW1lcyhhbGwpICVpbiUgdXNhYmxlX2l0ZW1zKV0KaW1wdXRlZE1lZGlhbiRDb250ZXh0IDwtIE5VTEwKc3VtKCEoY29sbmFtZXMoaW1wdXRlZE1lZGlhbikgJWluJSB1c2FibGVfaXRlbXMpKQphbGwgPC0gY2JpbmQoYWxsLGltcHV0ZWRNZWRpYW5bbWF0Y2gocm93bmFtZXMoaW1wdXRlZE1lZGlhbiksYWxsJFJlc3AuSUQpLF0pCmBgYAoKKipBZGQgc29tZSB1cGRhdGVzIHRoYXQgUmljaGkgZGlkIGluIERhdGUgN3RoIEp1bmUgMjAxOCoqCgpgYGB7ciBldmFsPUZBTFNFfQpPdGhlcl93YXlzX2FuZF9kZWdyZWVfcm9sZV93aXRoX3Jlc3BvbmRlbnRfSURzIDwtIHJlYWRfZXhjZWwoIk90aGVyLXdheXMtYW5kLWRlZ3JlZS1yb2xlLXdpdGgtcmVzcG9uZGVudC1JRHMueGxzeCIpCnN1bShPdGhlcl93YXlzX2FuZF9kZWdyZWVfcm9sZV93aXRoX3Jlc3BvbmRlbnRfSURzJFJlc3AuSUQgIT0gT3RoZXJfd2F5c19hbmRfZGVncmVlX3JvbGVfd2l0aF9yZXNwb25kZW50X0lEcyRSZXNwLklEX18xKQojIHRvIHJlcGxhY2UgCiMgbWF0Y2ggZm9yIHRoZSBOQSBkZWdyZWUucm9sZQoKbWF0Y2hfdXBkYXRlcyA8LSBtYXRjaChhbGwkUmVzcC5JRCxPdGhlcl93YXlzX2FuZF9kZWdyZWVfcm9sZV93aXRoX3Jlc3BvbmRlbnRfSURzJFJlc3AuSUQpCmFsbCRwcml2YXRlLmxlc3NvbnMxLm90aGVyLndheXNbbWF0Y2hfdXBkYXRlc10gPC0gT3RoZXJfd2F5c19hbmRfZGVncmVlX3JvbGVfd2l0aF9yZXNwb25kZW50X0lEcyRwcml2YXRlLmxlc3NvbnMxLm90aGVyLndheXMKYWxsJHN0dWR5LmhvbGlkYXkyLm90aGVyLndheXNbbWF0Y2hfdXBkYXRlc10gPC0gT3RoZXJfd2F5c19hbmRfZGVncmVlX3JvbGVfd2l0aF9yZXNwb25kZW50X0lEcyRzdHVkeS5ob2xpZGF5Mi5vdGhlci53YXlzCmFsbCR5ZWFyLnNlbS5hYnJvYWQzLm90aGVyLndheXNbbWF0Y2hfdXBkYXRlc10gPC0gT3RoZXJfd2F5c19hbmRfZGVncmVlX3JvbGVfd2l0aF9yZXNwb25kZW50X0lEcyR5ZWFyLnNlbS5hYnJvYWQzLm90aGVyLndheXMKYWxsJG9ubGluZS5jb3Vyc2U0Lm90aGVyLndheXNbbWF0Y2hfdXBkYXRlc10gPC0gT3RoZXJfd2F5c19hbmRfZGVncmVlX3JvbGVfd2l0aF9yZXNwb25kZW50X0lEcyRvbmxpbmUuY291cnNlNC5vdGhlci53YXlzCmFsbCRvdGhlcjUub3RoZXIud2F5c1ttYXRjaF91cGRhdGVzXSA8LSBPdGhlcl93YXlzX2FuZF9kZWdyZWVfcm9sZV93aXRoX3Jlc3BvbmRlbnRfSURzJG90aGVyNS5vdGhlci53YXlzCmFsbCRkZWdyZWUucm9sZVttYXRjaF91cGRhdGVzXSA8LSBPdGhlcl93YXlzX2FuZF9kZWdyZWVfcm9sZV93aXRoX3Jlc3BvbmRlbnRfSURzJGRlZ3JlZS5yb2xlCmBgYAoKIyMgU2F2ZSBpbXB1dGVkIGRhdGEKCmBgYHtyfQp3cml0ZS5jc3YoYWxsLCIwMi1kZXNjcmlwdGl2ZV9kYXRhL21lcmdlZF9maWx0ZXJlZF9pbXB1dGVkTWVkaWFuX2xpa2VydE51bWJlci5jc3YiLHJvdy5uYW1lcyA9IEZBTFNFKQpgYGAKCiMgQmFycGxvdCBvZiBsaWtlcnQgdmFyaWFibGVzCgpgYGB7ciBmaWcud2lkdGg9MjAsZmlnLmhlaWdodD0yMH0KYWxsX21lbHQgPC0gbWVsdChhbGwsaWQudmFycyA9IGMoIlJlc3AuSUQiLCJHZW5kZXIiLCJBZ2UiLCJwcm9mIiwiQ29udGV4dCIsInN0dWR5LnllYXIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gbGlrZXJ0X3ZhcmlhYmxlczEpCgphbGxfbWVsdCR2YWx1ZSA8LSBmYWN0b3IoYWxsX21lbHQkdmFsdWUsbGV2ZWxzPWMoMSwyLDMsNCw1KSxsYWJlbHM9YygiU3Ryb25nbHkgZGlzYWdyZWUiLCJEaXNhZ3JlZSIsIk5vdCBzdXJlIiwiQWdyZWUiLCJTdHJvbmdseSBhZ3JlZSIpKQojIGRpbShhbGxfbWVsdCkKIyAzMjMqbGVuZ3RoKGxpa2VydF92YXJpYWJsZXMxKQoKYWxsX21lbHQgPC0gYWxsX21lbHQgJT4lIHNlcGFyYXRlKHZhcmlhYmxlLGludG89YygiaXRlbSIsInR5cGUiKSxzZXA9IlxcLiIscmVtb3ZlPUZBTFNFKQpnZ3Bsb3QoYWxsX21lbHQsYWVzKHg9dmFyaWFibGUsZmlsbD12YWx1ZSkpICsgZ2VvbV9iYXIocG9zaXRpb24gPSAic3RhY2siLGNvbG91cj0iYmxhY2siKSArIAogIGZhY2V0X2dyaWQoQ29udGV4dH50eXBlLHNjYWxlcyA9ICJmcmVlIikrdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSxheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9OCkpICsgZ2d0aXRsZSgiRmlsdGVyZWQgZGF0YXNldCIpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiNjYTAwMjAiLCIjZjRhNTgyIiwiI2ZmZmZiZiIsIiNhYmQ5ZTkiLCIjMmM3YmI2IiwiZ3JleSIpKQoKZmlsdF9zdW0gPC0gYWxsX21lbHQgJT4lIGdyb3VwX2J5KENvbnRleHQsdmFyaWFibGUsdHlwZSx2YWx1ZSkgJT4lIGRwbHlyOjpzdW1tYXJpc2UoTmdyb3VwPWxlbmd0aCh2YWx1ZSkpCmdncGxvdChmaWx0X3N1bSxhZXMoeD12YWx1ZSx5PU5ncm91cCxjb2xvdXI9Q29udGV4dCxncm91cD1pbnRlcmFjdGlvbih2YXJpYWJsZSwgQ29udGV4dCkpKSArIGdlb21fbGluZSgpICsgZ2VvbV9wb2ludCgpICsgZmFjZXRfd3JhcCh+dHlwZSxzY2FsZXMgPSAiZnJlZSIpK3RoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCgpgYGAKCiMjIEJhcnBsb3Qgb2YgRWR1Y2F0ZWQgYW5kIE5lY2Vzc2l0eSBpbiB0aGUgQXVzdHJhbGlhbiBhbmQgRXVyb3BlYW4gQ29udGV4dHMKCi0gKipFZHVjYXRlZCoqCgpgYGB7cn0KIyBhZGQgbnVtYmVycyBvbiB0aGUgYmFyCmVkdWNhdGVkIDwtIGFsbFthbGwkQ29udGV4dCAlaW4lIGMoIkdlcm1hbiBpbiBBdXN0cmFsaWEiLCJJdGFsaWFuIGluIEF1c3RyYWxpYSIpLF0KdGFibGUoZWR1Y2F0ZWQkZWR1Y2F0ZWQxLGVkdWNhdGVkJENvbnRleHQsdXNlTkE9ImFsd2F5cyIpCmVkdWNhdGVkJGVkdWNhdGVkMSA8LSBmYWN0b3IoZWR1Y2F0ZWQkZWR1Y2F0ZWQxLGxldmVscyA9IGMoMSwyLDMsNCw1KSxsYWJlbHM9YygiU3Ryb25nbHkgZGlzYWdyZWUiLCJEaXNhZ3JlZSIsIk5vdCBzdXJlIiwiQWdyZWUiLCJTdHJvbmdseSBhZ3JlZSIpKSAKCnRhYkVkdSA8LSB0KHRhYmxlKGVkdWNhdGVkJGVkdWNhdGVkMSxlZHVjYXRlZCRDb250ZXh0KSkKZ2dkZiA8LSBkYXRhLmZyYW1lKEVkdWNhdGVkID0gcmVwKGNvbG5hbWVzKHRhYkVkdSksZWFjaD0yKSwKICBOLlBhcnRpY2lwYW50cyA9IGFzLm51bWVyaWModGFiRWR1KSwKICBDb250ZXh0ID0gcmVwKHJvd25hbWVzKHRhYkVkdSksdGltZXM9NSkpCgoKZ2dwbG90KGdnZGYsYWVzKHg9RWR1Y2F0ZWQseT1OLlBhcnRpY2lwYW50cyxmaWxsPUNvbnRleHQpKSArIGdlb21fYmFyKHBvc2l0aW9uPSJkb2RnZSIsY29sb3VyPSJ3aGl0ZSIsc3RhdD0iaWRlbnRpdHkiKSAgKyBsYWJzKHk9Ik4gcGFydGljaXBhbnRzIikgKyBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDM1LDEwKSxsaW1pdHM9YygwLDM1KSkgKyB0aGVtZV9idygpICsgZ2d0aXRsZSgiRWR1Y2F0ZWQgYnkgQ29udGV4dCIpKyAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IE4uUGFydGljaXBhbnRzKSwgaGp1c3Q9MC41LCB2anVzdD0tMC4yNSwgc2l6ZSA9IDIuNSxwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjkpKSAKZ2dwbG90KGdnZGYsYWVzKHg9Q29udGV4dCx5PU4uUGFydGljaXBhbnRzLGZpbGw9RWR1Y2F0ZWQpKSArIGdlb21fYmFyKHBvc2l0aW9uPSJkb2RnZSIsY29sb3VyPSJ3aGl0ZSIsc3RhdD0iaWRlbnRpdHkiKSAgKyBsYWJzKHk9Ik4gcGFydGljaXBhbnRzIikgKyBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDM1LDEwKSxsaW1pdHM9YygwLDM1KSkgKyB0aGVtZV9idygpICsgZ2d0aXRsZSgiRWR1Y2F0ZWQgYnkgQ29udGV4dCIpKyAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IE4uUGFydGljaXBhbnRzKSwgaGp1c3Q9MC41LCB2anVzdD0tMC4yNSwgc2l6ZSA9IDIuNSxwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjkpKSAKYGBgCgotICoqTmVjZXNzaXR5KioKCmBgYHtyfQojIGFkZCBudW1iZXJzIG9uIHRoZSBiYXIKbmVjZXNzaXR5IDwtIGFsbFthbGwkQ29udGV4dCAlaW4lIGMoIkVuZ2xpc2ggaW4gR2VybWFueSIsIkVuZ2xpc2ggaW4gSXRhbHkiKSxdCnRhYmxlKG5lY2Vzc2l0eSRuZWNlc3NpdHkxLG5lY2Vzc2l0eSRDb250ZXh0LHVzZU5BPSJhbHdheXMiKQpuZWNlc3NpdHkkbmVjZXNzaXR5MSA8LSBmYWN0b3IobmVjZXNzaXR5JG5lY2Vzc2l0eTEsbGV2ZWxzID0gYygxLDIsMyw0LDUpLGxhYmVscz1jKCJTdHJvbmdseSBkaXNhZ3JlZSIsIkRpc2FncmVlIiwiTm90IHN1cmUiLCJBZ3JlZSIsIlN0cm9uZ2x5IGFncmVlIikpIAoKdGFiTmVjIDwtIHQodGFibGUobmVjZXNzaXR5JG5lY2Vzc2l0eTEsbmVjZXNzaXR5JENvbnRleHQsdXNlTkEgPSAiYWx3YXlzIikpWy0zLF0KZ2dkZiA8LSBkYXRhLmZyYW1lKE5lY2Vzc2l0eSA9IHJlcChjb2xuYW1lcyh0YWJOZWMpLGVhY2g9MiksCiAgTi5QYXJ0aWNpcGFudHMgPSBhcy5udW1lcmljKHRhYk5lYyksCiAgQ29udGV4dCA9IHJlcChyb3duYW1lcyh0YWJOZWMpLHRpbWVzPTYpKQoKCmdncGxvdChnZ2RmLGFlcyh4PU5lY2Vzc2l0eSx5PU4uUGFydGljaXBhbnRzLGZpbGw9Q29udGV4dCkpICsgZ2VvbV9iYXIocG9zaXRpb249ImRvZGdlIixjb2xvdXI9IndoaXRlIixzdGF0PSJpZGVudGl0eSIpICArIGxhYnMoeT0iTiBwYXJ0aWNpcGFudHMiKSArIHNjYWxlX3lfY29udGludW91cyhicmVha3M9c2VxKDAsNDAsMTApLGxpbWl0cz1jKDAsNDApKSArIHRoZW1lX2J3KCkgKyBnZ3RpdGxlKCJOZWNlc3NpdHkgYnkgQ29udGV4dCIpKyAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IE4uUGFydGljaXBhbnRzKSwgaGp1c3Q9MC41LCB2anVzdD0tMC4yNSwgc2l6ZSA9IDIuNSxwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSh3aWR0aD0wLjkpKSAKZ2dwbG90KGdnZGYsYWVzKHg9Q29udGV4dCx5PU4uUGFydGljaXBhbnRzLGZpbGw9TmVjZXNzaXR5KSkgKyBnZW9tX2Jhcihwb3NpdGlvbj0iZG9kZ2UiLGNvbG91cj0id2hpdGUiLHN0YXQ9ImlkZW50aXR5IikgICsgbGFicyh5PSJOIHBhcnRpY2lwYW50cyIpICsgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1zZXEoMCwzNSwxMCksbGltaXRzPWMoMCwzNSkpICsgdGhlbWVfYncoKSArIGdndGl0bGUoIk5lY2Vzc2l0eSBieSBDb250ZXh0IikrICBnZW9tX3RleHQoYWVzKGxhYmVsID0gTi5QYXJ0aWNpcGFudHMpLCBoanVzdD0wLjUsIHZqdXN0PS0wLjI1LCBzaXplID0gMi41LHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuOSkpIApgYGAKCiMgQ29ycmVsYXRpb24gcGxvdCBvZiBpdGVtcyBieSBjb250ZXh0CgojIyBJdGFsaWFuIGluIEF1c3RyYWxpYQoKYGBge3IgY29yX2l0YWxpYW5faW5fYXVzdHJhbGlhLGZpZy53aWR0aD0xNSxmaWcuaGVpZ2h0PTE1fQpjb3YgPC0gY29yKGZpbHRlcmVkX2NvbnZbZmlsdGVyZWRfY29udiRDb250ZXh0ID09ICJJdGFsaWFuIGluIEF1c3RyYWxpYSIsbGlrZXJ0X3ZhcmlhYmxlczFbIShsaWtlcnRfdmFyaWFibGVzMSAlaW4lICJuZWNlc3NpdHkxIildXSxtZXRob2QgPSAicGVhcnNvbiIsdXNlPSJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQpkYXRhX2Nvcl9pdGFfaW5fYXUgPC0gZGF0YS5mcmFtZShjb3JfaXRhX2luX2F1PWNvdltsb3dlci50cmkoY292LCBkaWFnID0gVFJVRSldLAogICAgICAgICAgICAgICAgdmFyMSA9IHJvd25hbWVzKGNvdilbdW5saXN0KHQobWFwcGx5KCI6IiwgMTpucm93KGNvdiksIG5yb3coY292KSkpWzEsXSldLAogICAgICAgICAgICAgICAgdmFyMiA9IHJlcChjb2xuYW1lcyhjb3YpLHRpbWVzPXJldihzZXEobnJvdyhjb3YpOjEpKSkpCgpyb3dfaW5mb3MgPC0gZGF0YS5mcmFtZShWYXJpYWJsZXM9c2FwcGx5KHN0cnNwbGl0KGNvbG5hbWVzKGNvdiksc3BsaXQ9IlxcLiIpLGZ1bmN0aW9uKHgpIHhbMl0pKQpyb3dfaW5mb3MkVmFyaWFibGVzIDwtIGFzLmNoYXJhY3Rlcihyb3dfaW5mb3MkVmFyaWFibGVzKQpyb3duYW1lcyhyb3dfaW5mb3MpIDwtIHJvd25hbWVzKGNvdikKcm93X2luZm9zJFZhcmlhYmxlc1t3aGljaChpcy5uYShyb3dfaW5mb3MkVmFyaWFibGVzKSldIDwtIGMoImVkdWNhdGVkIikKcm93X2luZm9zIDwtIHJvd19pbmZvc1tvcmRlcihyb3dfaW5mb3MkVmFyaWFibGVzKSwsZHJvcD1GQUxTRV0KCmFubl9jb2xfd2lkZSA8LSBkYXRhLmZyYW1lKFZhcmlhYmxlPXVuaXF1ZShyb3dfaW5mb3MkVmFyaWFibGVzKSkKYW5uX2NvbG9yc193aWRlIDwtIGxpc3QoVmFyaWFibGVzPWMoY29tbTE9IiNiZDAwMjYiLGVkdWNhdGVkPSIjYjM1ODA2IiwgaWQxPSIjZjZlOGMzIixpbnN0cnUxPSIjMzU5NzhmIixpbnRlZ3IxPSIjMzg2Y2IwIixpbnRyMT0iI2ZmZmY5OSIsb3VnaHQxPSJncmV5Iixwb3N0MT0iYmxhY2siLHByb2YxPSJwaW5rIikpCgojcGhlYXRtYXAoY292LCBtYWluID0gIkl0YWxpYW4gaW4gQXVzdHJhbGlhIixhbm5vdGF0aW9uX25hbWVzX3JvdyA9IEZBTFNFLGNsdXN0ZXJfY29scz1UUlVFLGNsdXN0ZXJfcm93cz1UUlVFLGFubm90YXRpb25fY29sID0gcm93X2luZm9zWywxLGRyb3A9RkFMU0VdLCBhbm5vdGF0aW9uX3JvdyA9IHJvd19pbmZvc1ssMSxkcm9wPUZBTFNFXSwgIGFubm90YXRpb25fY29sb3JzID0gYW5uX2NvbG9yc193aWRlLGJyZWFrcz1zZXEoLTEsMSwwLjIpLGNvbD1jKCIjNjcwMDFmIiwiI2IyMTgyYiIsIiNkNjYwNGQiLCIjZjRhNTgyIiwiI2ZkZGJjNyIsIiNmN2Y3ZjciLCIjZDFlNWYwIiwiIzkyYzVkZSIsIiM0MzkzYzMiLCIjMjE2NmFjIiwiIzA1MzA2MSIpLHNob3dfY29sbmFtZXMgPSBGQUxTRSx3aWR0aCA9IDcsaGVpZ2h0ID0gNykKIyMjIyMjIyMjIyMjIyMjIyMjIwoKZGlhZyhjb3YpIDwtIE5BCnBoZWF0bWFwKGNvdiwgbWFpbiA9ICJJdGFsaWFuIGluIEF1c3RyYWxpYSIsYW5ub3RhdGlvbl9uYW1lc19yb3cgPSBGQUxTRSxjbHVzdGVyX2NvbHM9VFJVRSxjbHVzdGVyX3Jvd3M9VFJVRSxhbm5vdGF0aW9uX2NvbCA9IHJvd19pbmZvc1ssMSxkcm9wPUZBTFNFXSwgYW5ub3RhdGlvbl9yb3cgPSByb3dfaW5mb3NbLDEsZHJvcD1GQUxTRV0KLCAgYW5ub3RhdGlvbl9jb2xvcnMgPSBhbm5fY29sb3JzX3dpZGUsc2hvd19jb2xuYW1lcyA9IEZBTFNFLGJyZWFrcyA9IHNlcSgtMC42LDAuNyxsZW5ndGgub3V0ID0gNTApLHdpZHRoID0gNyxoZWlnaHQgPSA3LGNvbG9yPWNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbChuID0gNywgbmFtZSA9ICJSZEJ1IikpKDUwKSkKCmNvdl9JdGFBdXMgPC0gY292CmBgYAoKIyMgR2VybWFuIGluIEF1c3RyYWxpYQoKYGBge3IgY29yX2dlcm1hbl9pbl9hdXN0cmFsaWEsZmlnLndpZHRoPTE1LGZpZy5oZWlnaHQ9MTV9CmNvdiA8LSBjb3IoZmlsdGVyZWRfY29udltmaWx0ZXJlZF9jb252JENvbnRleHQgPT0gIkdlcm1hbiBpbiBBdXN0cmFsaWEiLGxpa2VydF92YXJpYWJsZXMxWyEobGlrZXJ0X3ZhcmlhYmxlczEgJWluJSAibmVjZXNzaXR5MSIpXV0sbWV0aG9kID0gInBlYXJzb24iLHVzZT0icGFpcndpc2UuY29tcGxldGUub2JzIikKZGF0YV9jb3JfZ2VybV9pbl9hdSA8LSBkYXRhLmZyYW1lKGNvcl9nZXJtX2luX2F1PWNvdltsb3dlci50cmkoY292LCBkaWFnID0gVFJVRSldLAogICAgICAgICAgICAgICAgdmFyMSA9IHJvd25hbWVzKGNvdilbdW5saXN0KHQobWFwcGx5KCI6IiwgMTpucm93KGNvdiksIG5yb3coY292KSkpWzEsXSldLAogICAgICAgICAgICAgICAgdmFyMiA9IHJlcChjb2xuYW1lcyhjb3YpLHRpbWVzPXJldihzZXEobnJvdyhjb3YpOjEpKSkpCgoKCnJvd19pbmZvcyA8LSBkYXRhLmZyYW1lKFZhcmlhYmxlcz1zYXBwbHkoc3Ryc3BsaXQoY29sbmFtZXMoY292KSxzcGxpdD0iXFwuIiksZnVuY3Rpb24oeCkgeFsyXSkpCnJvd19pbmZvcyRWYXJpYWJsZXMgPC0gYXMuY2hhcmFjdGVyKHJvd19pbmZvcyRWYXJpYWJsZXMpCnJvd25hbWVzKHJvd19pbmZvcykgPC0gcm93bmFtZXMoY292KQpyb3dfaW5mb3MkVmFyaWFibGVzW3doaWNoKGlzLm5hKHJvd19pbmZvcyRWYXJpYWJsZXMpKV0gPC0gYygiZWR1Y2F0ZWQiKQpyb3dfaW5mb3MgPC0gcm93X2luZm9zW29yZGVyKHJvd19pbmZvcyRWYXJpYWJsZXMpLCxkcm9wPUZBTFNFXQoKYW5uX2NvbF93aWRlIDwtIGRhdGEuZnJhbWUoVmFyaWFibGU9dW5pcXVlKHJvd19pbmZvcyRWYXJpYWJsZXMpKQphbm5fY29sb3JzX3dpZGUgPC0gbGlzdChWYXJpYWJsZXM9Yyhjb21tMT0iI2JkMDAyNiIsZWR1Y2F0ZWQ9IiNiMzU4MDYiLCBpZDE9IiNmNmU4YzMiLGluc3RydTE9IiMzNTk3OGYiLGludGVncjE9IiMzODZjYjAiLGludHIxPSIjZmZmZjk5IixvdWdodDE9ImdyZXkiLHBvc3QxPSJibGFjayIscHJvZjE9InBpbmsiKSkKCmRpYWcoY292KSA8LSBOQQpwaGVhdG1hcChjb3YsIG1haW4gPSAiR2VybWFuIGluIEF1c3RyYWxpYSIsYW5ub3RhdGlvbl9uYW1lc19yb3cgPSBGQUxTRSxjbHVzdGVyX2NvbHM9VFJVRSxjbHVzdGVyX3Jvd3M9VFJVRSxhbm5vdGF0aW9uX2NvbCA9IHJvd19pbmZvc1ssMSxkcm9wPUZBTFNFXSwgYW5ub3RhdGlvbl9yb3cgPSByb3dfaW5mb3NbLDEsZHJvcD1GQUxTRV0KLCAgYW5ub3RhdGlvbl9jb2xvcnMgPSBhbm5fY29sb3JzX3dpZGUsc2hvd19jb2xuYW1lcyA9IEZBTFNFLGJyZWFrcyA9IHNlcSgtMC42LDAuNyxsZW5ndGgub3V0ID0gNTApLHdpZHRoID0gNyxoZWlnaHQgPSA3LGNvbG9yPWNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbChuID0gNywgbmFtZSA9ICJSZEJ1IikpKDUwKSkKCiMgCmNvdl9HZXJtQXVzIDwtIGNvdgpgYGAKCiMjIEVuZ2xpc2ggaW4gR2VybWFueQoKYGBge3IgY29yX2VuZ2xpc2hfaW5fZ2VybWFueSxmaWcud2lkdGg9MTUsZmlnLmhlaWdodD0xNX0KY292IDwtIGNvcihmaWx0ZXJlZF9jb252W2ZpbHRlcmVkX2NvbnYkQ29udGV4dCA9PSAiRW5nbGlzaCBpbiBHZXJtYW55IixsaWtlcnRfdmFyaWFibGVzMVshKGxpa2VydF92YXJpYWJsZXMxICVpbiUgYygicmVjb25uZWN0LmNvbW0xIiwgICAgInNwZWFrZXJzbWVsYi5jb21tMSIsImNvbWVjbG9zZXIuY29tbTEiLCJlZHVjYXRlZDEiKSldXSxtZXRob2QgPSAicGVhcnNvbiIsdXNlPSJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQpkYXRhX2Nvcl9lbmdfaW5fZ2VybSA8LSBkYXRhLmZyYW1lKGNvcl9lbmdfaW5fZ2VybT1jb3ZbbG93ZXIudHJpKGNvdiwgZGlhZyA9IFRSVUUpXSwKICAgICAgICAgICAgICAgIHZhcjEgPSByb3duYW1lcyhjb3YpW3VubGlzdCh0KG1hcHBseSgiOiIsIDE6bnJvdyhjb3YpLCBucm93KGNvdikpKVsxLF0pXSwKICAgICAgICAgICAgICAgIHZhcjIgPSByZXAoY29sbmFtZXMoY292KSx0aW1lcz1yZXYoc2VxKG5yb3coY292KToxKSkpKQoKCnJvd19pbmZvcyA8LSBkYXRhLmZyYW1lKFZhcmlhYmxlcz1zYXBwbHkoc3Ryc3BsaXQoY29sbmFtZXMoY292KSxzcGxpdD0iXFwuIiksZnVuY3Rpb24oeCkgeFsyXSkpCnJvd19pbmZvcyRWYXJpYWJsZXMgPC0gYXMuY2hhcmFjdGVyKHJvd19pbmZvcyRWYXJpYWJsZXMpCnJvd25hbWVzKHJvd19pbmZvcykgPC0gcm93bmFtZXMoY292KQpyb3dfaW5mb3MkVmFyaWFibGVzW3doaWNoKGlzLm5hKHJvd19pbmZvcyRWYXJpYWJsZXMpKV0gPC0gYygibmVjZXNzaXR5IikKcm93X2luZm9zIDwtIHJvd19pbmZvc1tvcmRlcihyb3dfaW5mb3MkVmFyaWFibGVzKSwsZHJvcD1GQUxTRV0KCmFubl9jb2xfd2lkZSA8LSBkYXRhLmZyYW1lKFZhcmlhYmxlPXVuaXF1ZShyb3dfaW5mb3MkVmFyaWFibGVzKSkKYW5uX2NvbG9yc193aWRlIDwtIGxpc3QoVmFyaWFibGVzPWMoaWQxPSIjZjZlOGMzIixuZWNlc3NpdHk9IiNiMzU4MDYiLGluc3RydTE9IiMzNTk3OGYiLGludGVncjE9IiMzODZjYjAiLGludHIxPSIjZmZmZjk5IixvdWdodDE9ImdyZXkiLHBvc3QxPSJibGFjayIscHJvZjE9InBpbmsiKSkKCmRpYWcoY292KSA8LSBOQQpwaGVhdG1hcChjb3YsIG1haW4gPSAiRW5nbGlzaCBpbiBHZXJtYW55Iixhbm5vdGF0aW9uX25hbWVzX3JvdyA9IEZBTFNFLGNsdXN0ZXJfY29scz1UUlVFLGNsdXN0ZXJfcm93cz1UUlVFLGFubm90YXRpb25fY29sID0gcm93X2luZm9zWywxLGRyb3A9RkFMU0VdLCBhbm5vdGF0aW9uX3JvdyA9IHJvd19pbmZvc1ssMSxkcm9wPUZBTFNFXQosICBhbm5vdGF0aW9uX2NvbG9ycyA9IGFubl9jb2xvcnNfd2lkZSxzaG93X2NvbG5hbWVzID0gRkFMU0UsYnJlYWtzID0gc2VxKC0wLjYsMC43LGxlbmd0aC5vdXQgPSA1MCksd2lkdGggPSA3LGhlaWdodCA9IDcsY29sb3I9Y29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKG4gPSA3LCBuYW1lID0gIlJkQnUiKSkoNTApKQoKY292X0VuZ0dlcm0gPC0gY292CmBgYAoKIyMgRW5nbGlzaCBpbiBJdGFseQoKYGBge3IgY29yX2VuZ2xpc2hfaW5faXRhbHksZmlnLndpZHRoPTE1LGZpZy5oZWlnaHQ9MTV9CmNvdiA8LSBjb3IoZmlsdGVyZWRfY29udltmaWx0ZXJlZF9jb252JENvbnRleHQgPT0gIkVuZ2xpc2ggaW4gSXRhbHkiLGxpa2VydF92YXJpYWJsZXMxWyEobGlrZXJ0X3ZhcmlhYmxlczEgJWluJSBjKCJyZWNvbm5lY3QuY29tbTEiLCJzcGVha2Vyc21lbGIuY29tbTEiLCJjb21lY2xvc2VyLmNvbW0xIiwiZWR1Y2F0ZWQxIikpXV0sbWV0aG9kID0gInBlYXJzb24iLHVzZT0icGFpcndpc2UuY29tcGxldGUub2JzIikKZGF0YV9jb3JfZW5nX2luX2l0YSA8LSBkYXRhLmZyYW1lKGNvcl9lbmdfaW5faXRhPWNvdltsb3dlci50cmkoY292LCBkaWFnID0gVFJVRSldLAogICAgICAgICAgICAgICAgdmFyMSA9IHJvd25hbWVzKGNvdilbdW5saXN0KHQobWFwcGx5KCI6IiwgMTpucm93KGNvdiksIG5yb3coY292KSkpWzEsXSldLAogICAgICAgICAgICAgICAgdmFyMiA9IHJlcChjb2xuYW1lcyhjb3YpLHRpbWVzPXJldihzZXEobnJvdyhjb3YpOjEpKSkpCgoKcm93X2luZm9zIDwtIGRhdGEuZnJhbWUoVmFyaWFibGVzPXNhcHBseShzdHJzcGxpdChjb2xuYW1lcyhjb3YpLHNwbGl0PSJcXC4iKSxmdW5jdGlvbih4KSB4WzJdKSkKcm93X2luZm9zJFZhcmlhYmxlcyA8LSBhcy5jaGFyYWN0ZXIocm93X2luZm9zJFZhcmlhYmxlcykKcm93bmFtZXMocm93X2luZm9zKSA8LSByb3duYW1lcyhjb3YpCnJvd19pbmZvcyRWYXJpYWJsZXNbd2hpY2goaXMubmEocm93X2luZm9zJFZhcmlhYmxlcykpXSA8LSAibmVjZXNzaXR5Igpyb3dfaW5mb3MgPC0gcm93X2luZm9zW29yZGVyKHJvd19pbmZvcyRWYXJpYWJsZXMpLCxkcm9wPUZBTFNFXQoKYW5uX2NvbF93aWRlIDwtIGRhdGEuZnJhbWUoVmFyaWFibGU9dW5pcXVlKHJvd19pbmZvcyRWYXJpYWJsZXMpKQphbm5fY29sb3JzX3dpZGUgPC0gbGlzdChWYXJpYWJsZXM9Yyhjb21tMT0iI2JkMDAyNiIsbmVjZXNzaXR5PSIjYjM1ODA2IiwgaWQxPSIjZjZlOGMzIixpbnN0cnUxPSIjMzU5NzhmIixpbnRlZ3IxPSIjMzg2Y2IwIixpbnRyMT0iI2ZmZmY5OSIsb3VnaHQxPSJncmV5Iixwb3N0MT0iYmxhY2siLHByb2YxPSJwaW5rIikpCgpkaWFnKGNvdikgPC0gTkEKcGhlYXRtYXAoY292LCBtYWluID0gIkVuZ2xpc2ggaW4gSXRhbHkiLGFubm90YXRpb25fbmFtZXNfcm93ID0gRkFMU0UsY2x1c3Rlcl9jb2xzPVRSVUUsY2x1c3Rlcl9yb3dzPVRSVUUsYW5ub3RhdGlvbl9jb2wgPSByb3dfaW5mb3NbLDEsZHJvcD1GQUxTRV0sIGFubm90YXRpb25fcm93ID0gcm93X2luZm9zWywxLGRyb3A9RkFMU0VdCiwgIGFubm90YXRpb25fY29sb3JzID0gYW5uX2NvbG9yc193aWRlLHNob3dfY29sbmFtZXMgPSBGQUxTRSxicmVha3MgPSBzZXEoLTAuNiwwLjcsbGVuZ3RoLm91dCA9IDUwKSx3aWR0aCA9IDcsaGVpZ2h0ID0gNyxjb2xvcj1jb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwobiA9IDcsIG5hbWUgPSAiUmRCdSIpKSg1MCkpCgojIApjb3ZfRW5nSXRhIDwtIGNvdgpgYGAKCiMjIENvcnJlbGF0aW9uIGJldHdlZW4gY29ycmVsYXRpb24gaW4gdGhlIGRpZmZlcmVudCBjb250ZXh0cwoKV2Ugd2lsbCBwZXJmb3JtIGFuIGV4cGxvcmF0b3J5IEZBIGNvbWJpbmluZyBhbGwgdGhlIGNvbnRleHRzIHRvZ2V0aGVyLiBUaGlzIG1lYW5zIHRoYXQgd2UgYXJlIGFzc3VtaW5nIHRoYXQgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gaXRlbXMgYWNyb3NzIGNvbnRleHQgaGFzIHRoZSBzYW1lIGRpcmVjdGlvbiAoZG9lcyBub3QgaGFwcGVuIHRoYXQgY29yKGl0ZW0xLGl0ZW0yKV9jb250ZXh0MSA+IDAgYW5kIGNvcihpdGVtMSxpdGVtMilfY29udGV4dDIgPCAwKS4gCgpgYGB7ciBmaWcud2lkdGg9MTAsZmlnLmhlaWdodD0xMH0KY29tbW9uIDwtIHJvd25hbWVzKGNvdl9FbmdJdGEpW3Jvd25hbWVzKGNvdl9FbmdJdGEpICVpbiUgcm93bmFtZXMoY292X0l0YUF1cyldCnN1bShyb3duYW1lcyhjb3ZfRW5nSXRhKSAhPSByb3duYW1lcyhjb3ZfRW5nR2VybSkpCnN1bShyb3duYW1lcyhjb3ZfRW5nSXRhKSAhPSByb3duYW1lcyhjb3ZfR2VybUF1cykpCnN1bShyb3duYW1lcyhjb3ZfRW5nSXRhKSAhPSByb3duYW1lcyhjb3ZfSXRhQXVzKSkKc3VtKHJvd25hbWVzKGNvdl9HZXJtQXVzKSAhPSByb3duYW1lcyhjb3ZfSXRhQXVzKSkKCmNvbW1vbl9FbmdJdGEgPC0gY292X0VuZ0l0YVtyb3duYW1lcyhjb3ZfRW5nSXRhKSAlaW4lIGNvbW1vbixjb2xuYW1lcyhjb3ZfRW5nSXRhKSAlaW4lIGNvbW1vbl0KY29tbW9uX0VuZ0dlcm0gPC0gY292X0VuZ0dlcm1bcm93bmFtZXMoY292X0VuZ0dlcm0pICVpbiUgY29tbW9uLGNvbG5hbWVzKGNvdl9FbmdHZXJtKSAlaW4lIGNvbW1vbl0KY29tbW9uX0dlcm1BdXMgPC0gY292X0dlcm1BdXNbcm93bmFtZXMoY292X0dlcm1BdXMpICVpbiUgY29tbW9uLGNvbG5hbWVzKGNvdl9HZXJtQXVzKSAlaW4lIGNvbW1vbl0KY29tbW9uX0l0YUF1cyA8LSBjb3ZfSXRhQXVzW3Jvd25hbWVzKGNvdl9JdGFBdXMpICVpbiUgY29tbW9uLGNvbG5hbWVzKGNvdl9JdGFBdXMpICVpbiUgY29tbW9uXQoKc3VtKHJvd25hbWVzKGNvbW1vbl9FbmdJdGEpICE9IGNvbG5hbWVzKGNvbW1vbl9FbmdJdGEpKQpzdW0ocm93bmFtZXMoY29tbW9uX0VuZ0dlcm0pICE9IGNvbG5hbWVzKGNvbW1vbl9FbmdHZXJtKSkKc3VtKHJvd25hbWVzKGNvbW1vbl9HZXJtQXVzKSAhPSBjb2xuYW1lcyhjb21tb25fR2VybUF1cykpCnN1bShyb3duYW1lcyhjb21tb25fSXRhQXVzKSAhPSBjb2xuYW1lcyhjb21tb25fSXRhQXVzKSkKCgpwYXIobWZyb3c9YygyLDMpKQpwbG90KGNvbW1vbl9FbmdJdGEsY29tbW9uX0VuZ0dlcm0pCmFibGluZShoPWMoMCwwLjMpLHY9YygwLDAuMyksbHR5PTIsY29sID0gImRhcmsgcmVkIikKYWJsaW5lKGE9MCxiPTEsbHR5PTIsY29sID0gImRhcmsgcmVkIikKcGxvdChjb21tb25fRW5nSXRhLGNvbW1vbl9HZXJtQXVzKQphYmxpbmUoaD1jKDAsMC4zKSx2PWMoMCwwLjMpLGx0eT0yLGNvbCA9ICJkYXJrIHJlZCIpCmFibGluZShhPTAsYj0xLGx0eT0yLGNvbCA9ICJkYXJrIHJlZCIpCnBsb3QoY29tbW9uX0VuZ0l0YSxjb21tb25fSXRhQXVzKQphYmxpbmUoaD1jKDAsMC4zKSx2PWMoMCwwLjMpLGx0eT0yLGNvbCA9ICJkYXJrIHJlZCIpCmFibGluZShhPTAsYj0xLGx0eT0yLGNvbCA9ICJkYXJrIHJlZCIpCgpwbG90KGNvbW1vbl9FbmdHZXJtLGNvbW1vbl9HZXJtQXVzKQphYmxpbmUoaD1jKDAsMC4zKSx2PWMoMCwwLjMpLGx0eT0yLGNvbCA9ICJkYXJrIHJlZCIpCmFibGluZShhPTAsYj0xLGx0eT0yLGNvbCA9ICJkYXJrIHJlZCIpCnBsb3QoY29tbW9uX0VuZ0dlcm0sY29tbW9uX0l0YUF1cykKYWJsaW5lKGg9YygwLDAuMyksdj1jKDAsMC4zKSxsdHk9Mixjb2wgPSAiZGFyayByZWQiKQphYmxpbmUoYT0wLGI9MSxsdHk9Mixjb2wgPSAiZGFyayByZWQiKQoKcGxvdChjb21tb25fR2VybUF1cyxjb21tb25fSXRhQXVzKQphYmxpbmUoaD1jKDAsMC4zKSx2PWMoMCwwLjMpLGx0eT0yLGNvbCA9ICJkYXJrIHJlZCIpCmFibGluZShhPTAsYj0xLGx0eT0yLGNvbCA9ICJkYXJrIHJlZCIpCgojIExhcmdlc3QgZGlmZmVyZW5jZXMKbG93X0VuZ0dlcm0gPC0gbG93ZXIudHJpKGNvbW1vbl9FbmdHZXJtKQpjb21tb25fRW5nR2VybVshbG93X0VuZ0dlcm1dIDwtIE5BCmNvbW1vbl9HZXJtQXVzWyEobG93ZXIudHJpKGNvbW1vbl9HZXJtQXVzKSldIDwtIE5BCmNvbW1vbl9JdGFBdXNbIShsb3dlci50cmkoY29tbW9uX0l0YUF1cykpXSA8LSBOQQpjb21tb25fRW5nSXRhWyEobG93ZXIudHJpKGNvbW1vbl9FbmdJdGEpKV0gPC0gTkEKCgptYXQgPC0gZGF0YS5mcmFtZShjb21tb25fRW5nR2VybT1jKGNvbW1vbl9FbmdHZXJtKSwKICAgICAgICAgICAgICAgICAgY29tbW9uX0VuZ0l0YT1jKGNvbW1vbl9FbmdJdGEpLAogICAgICAgICAgICAgICAgICBjb21tb25fR2VybUF1cyA9IGMoY29tbW9uX0dlcm1BdXMpLAogICAgICAgICAgICAgICAgICBjb21tb25fSXRhQXVzID0gYyhjb21tb25fSXRhQXVzKSwKICAgICAgICAgICAgICAgICAgY29tcGFyZSA9IHBhc3RlKHJvd25hbWVzKGNvbW1vbl9FbmdHZXJtKSxjb2xuYW1lcyhjb21tb25fRW5nR2VybSksc2VwPSIuIikpICU+JQogIGZpbHRlcighaXMubmEoY29tbW9uX0VuZ0dlcm0pKSAlPiUKICBzZXBhcmF0ZShjb21wYXJlLGludG89YygiaXRlbTEiLCJ2YXJpYWJsZTEiLCJpdGVtMiIsInZhcmlhYmxlMiIpLHJlbW92ZT1GQUxTRSxzZXA9IlsuXSIpICU+JQogIHVuaXRlKGdyb3VwLHZhcmlhYmxlMSx2YXJpYWJsZTIsc2VwPSIuIikKCmxpYnJhcnkoZ2dyZXBlbCkKZ2dwbG90KG1hdCxhZXMoeD1jb21tb25fRW5nR2VybSx5PWNvbW1vbl9HZXJtQXVzLGxhYmVsPWNvbXBhcmUsY29sb3VyPWdyb3VwKSkgKyBnZW9tX3BvaW50KGFscGhhPTAuNSxzaXplPTAuOCkgKyBnZW9tX3RleHQoc2l6ZT0yKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PWMoMCwwLjMpLGxpbmV0eXBlPSJkb3R0ZWQiLGNvbG91cj0iZGFyayByZWQiKSArCmdlb21fdmxpbmUoeGludGVyY2VwdD1jKDAsMC4zKSxsaW5ldHlwZT0iZG90dGVkIixjb2xvdXI9ImRhcmsgcmVkIikKCgpnZ3Bsb3QobWF0LGFlcyh4PWNvbW1vbl9FbmdHZXJtLHk9Y29tbW9uX0l0YUF1cyxsYWJlbD1jb21wYXJlLGNvbG91cj1ncm91cCkpICsgZ2VvbV9wb2ludChhbHBoYT0wLjUsc2l6ZT0wLjgpICsgZ2VvbV90ZXh0KHNpemU9MikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD1jKDAsMC4zKSxsaW5ldHlwZT0iZG90dGVkIixjb2xvdXI9ImRhcmsgcmVkIikgKwpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9YygwLDAuMyksbGluZXR5cGU9ImRvdHRlZCIsY29sb3VyPSJkYXJrIHJlZCIpCgpnZ3Bsb3QobWF0LGFlcyh4PWNvbW1vbl9FbmdHZXJtLHk9Y29tbW9uX0VuZ0l0YSxsYWJlbD1jb21wYXJlLGNvbG91cj1ncm91cCkpICsgZ2VvbV9wb2ludChhbHBoYT0wLjUsc2l6ZT0wLjgpICsgZ2VvbV90ZXh0KHNpemU9MikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD1jKDAsMC4zKSxsaW5ldHlwZT0iZG90dGVkIixjb2xvdXI9ImRhcmsgcmVkIikgKwpnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9YygwLDAuMyksbGluZXR5cGU9ImRvdHRlZCIsY29sb3VyPSJkYXJrIHJlZCIpCgpgYGAKCgojIyBEaWZmZXJlbnQgY29ycmVsYXRpb24gcGxvdCBhbmQgUGVhcnNvbidzIGNvcnJlbGF0aW9uCgpgYGB7ciBmaWcud2lkdGg9MTIsZmlnLmhlaWdodD04LCBpbmNsdWRlPUZBTFNFfQpjb21tb24gPC0gcm93bmFtZXMoY292X0VuZ0l0YSlbcm93bmFtZXMoY292X0VuZ0l0YSkgJWluJSByb3duYW1lcyhjb3ZfSXRhQXVzKV0Kc3VtKHJvd25hbWVzKGNvdl9FbmdJdGEpICE9IHJvd25hbWVzKGNvdl9FbmdHZXJtKSkKc3VtKHJvd25hbWVzKGNvdl9FbmdJdGEpICE9IHJvd25hbWVzKGNvdl9HZXJtQXVzKSkKc3VtKHJvd25hbWVzKGNvdl9FbmdJdGEpICE9IHJvd25hbWVzKGNvdl9JdGFBdXMpKQpzdW0ocm93bmFtZXMoY292X0dlcm1BdXMpICE9IHJvd25hbWVzKGNvdl9JdGFBdXMpKQoKY29tbW9uX0VuZ0l0YSA8LSBjb3ZfRW5nSXRhW3Jvd25hbWVzKGNvdl9FbmdJdGEpICVpbiUgY29tbW9uLGNvbG5hbWVzKGNvdl9FbmdJdGEpICVpbiUgY29tbW9uXQpjb21tb25fRW5nR2VybSA8LSBjb3ZfRW5nR2VybVtyb3duYW1lcyhjb3ZfRW5nR2VybSkgJWluJSBjb21tb24sY29sbmFtZXMoY292X0VuZ0dlcm0pICVpbiUgY29tbW9uXQpjb21tb25fR2VybUF1cyA8LSBjb3ZfR2VybUF1c1tyb3duYW1lcyhjb3ZfR2VybUF1cykgJWluJSBjb21tb24sY29sbmFtZXMoY292X0dlcm1BdXMpICVpbiUgY29tbW9uXQpjb21tb25fSXRhQXVzIDwtIGNvdl9JdGFBdXNbcm93bmFtZXMoY292X0l0YUF1cykgJWluJSBjb21tb24sY29sbmFtZXMoY292X0l0YUF1cykgJWluJSBjb21tb25dCgpzdW0ocm93bmFtZXMoY29tbW9uX0VuZ0l0YSkgIT0gY29sbmFtZXMoY29tbW9uX0VuZ0l0YSkpCnN1bShyb3duYW1lcyhjb21tb25fRW5nR2VybSkgIT0gY29sbmFtZXMoY29tbW9uX0VuZ0dlcm0pKQpzdW0ocm93bmFtZXMoY29tbW9uX0dlcm1BdXMpICE9IGNvbG5hbWVzKGNvbW1vbl9HZXJtQXVzKSkKc3VtKHJvd25hbWVzKGNvbW1vbl9JdGFBdXMpICE9IGNvbG5hbWVzKGNvbW1vbl9JdGFBdXMpKQoKY29udGV4dHNfZGYgPC0gZGF0YS5mcmFtZSh4ID0gYygiY29tbW9uX0VuZ0l0YSIsImNvbW1vbl9FbmdJdGEiLCJjb21tb25fRW5nSXRhIiwKImNvbW1vbl9FbmdHZXJtIiwiY29tbW9uX0VuZ0dlcm0iLAoiY29tbW9uX0dlcm1BdXMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gYygiY29tbW9uX0VuZ0dlcm0iLCJjb21tb25fSXRhQXVzIiwiY29tbW9uX0dlcm1BdXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJjb21tb25fR2VybUF1cyIsImNvbW1vbl9JdGFBdXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImNvbW1vbl9JdGFBdXMiKSkgJT4lCiAgdGlkeXI6OnVuaXRlKG5hbWUseCx5LHNlcD0iLSIscmVtb3ZlPUZBTFNFKQoKc2NvciA8LSB2ZWN0b3IoImxpc3QiLGxlbmd0aD1ucm93KGNvbnRleHRzX2RmKSkKbmFtZXMoc2NvcikgPC0gY29udGV4dHNfZGYkbmFtZQpuYW1lc19wbG90IDwtIHBhc3RlMCgicCIsMTpucm93KGNvbnRleHRzX2RmKSkKbmFtZXNfcGxvdDEgPC0gcGFzdGUwKCJwX3ZhcjFfIiwxOm5yb3coY29udGV4dHNfZGYpKQpuYW1lc19wbG90MiA8LSBwYXN0ZTAoInBfdmFyMl8iLDE6bnJvdyhjb250ZXh0c19kZikpCgpmb3IoaSBpbiAxOm5yb3coY29udGV4dHNfZGYpKSB7CiAgCiAgY29tcCA8LSBjb250ZXh0c19kZltpLF0KICBjb250MSA8LSBnZXQoYXMuY2hhcmFjdGVyKGNvbXAkeCkpCiAgY29udDIgPC0gZ2V0KGFzLmNoYXJhY3Rlcihjb21wJHkpKQogIAogIG5hbWVzX2NvbXAgPC0gZGF0YS5mcmFtZShpdGVtMSA9IHJlcChjb2xuYW1lcyhjb250MSksZWFjaD1uY29sKGNvbnQxKSksCiAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtMiA9IHJlcChjb2xuYW1lcyhjb250MSksCiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVzPW5jb2woY29udDEpKSkgJT4lCiAgdGlkeXI6OnVuaXRlKG5hbWVfY29tcCwgaXRlbTEsaXRlbTIsc2VwPSItIixyZW1vdmU9RkFMU0UpICU+JQogIHRpZHlyOjp1bml0ZShuYW1lX2NvbXAxLCBpdGVtMixpdGVtMSxzZXA9Ii0iLHJlbW92ZT1GQUxTRSkgJT4lCiAgZHBseXI6Om11dGF0ZShjb250MV92ZWMgPSBjKGNvbnQxKSwKICAgICAgICAgICAgICAgIGNvbnQyX3ZlYyA9IGMoY29udDIpKSAlPiUKICBkcGx5cjo6ZmlsdGVyKG5hbWVfY29tcCAhPSBuYW1lX2NvbXAxKSAlPiUKICAgIHRpZHlyOjpzZXBhcmF0ZShpdGVtMSAsIGludG89YygidHlwZTEiLCJ2YXJpYWJsZTEiKSxzZXA9IlsuXSIscmVtb3ZlPUZBTFNFKSAlPiUKICAgIHRpZHlyOjpzZXBhcmF0ZShpdGVtMiAsIGludG89YygidHlwZTIiLCJ2YXJpYWJsZTIiKSxzZXA9IlsuXSIscmVtb3ZlPUZBTFNFKQoKc2NvcltbaV1dID0gY29yKG5hbWVzX2NvbXAkY29udDFfdmVjLG5hbWVzX2NvbXAkY29udDJfdmVjKQphc3NpZ24obmFtZXNfcGxvdFtpXSxnZ3Bsb3QobmFtZXNfY29tcCxhZXMoeD1jb250MV92ZWMseT1jb250Ml92ZWMpKSArIGdlb21faGV4KCkrCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygtMC4zLDAuMyksbGluZXR5cGU9ImRvdHRlZCIsY29sb3VyPSJkYXJrIHJlZCIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBjKC0wLjMsMC4zKSxsaW5ldHlwZT0iZG90dGVkIixjb2xvdXI9ImRhcmsgcmVkIikrCiAgbGFicyh4PXBhc3RlMChnc3ViKCJjb21tb25fIiwiIixhcy5jaGFyYWN0ZXIoY29tcCR4KSkpLHk9Z3N1YigiY29tbW9uXyIsIiIsYXMuY2hhcmFjdGVyKGNvbXAkeSkpKSkKICAKYXNzaWduKG5hbWVzX3Bsb3QxW2ldLGdncGxvdChuYW1lc19jb21wLGFlcyh4PWNvbnQxX3ZlYyx5PWNvbnQyX3ZlYyxjb2xvdXI9dmFyaWFibGUxKSkgKyBnZW9tX3BvaW50KCkrCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygtMC4zLDAuMyksbGluZXR5cGU9ImRvdHRlZCIsY29sb3VyPSJkYXJrIHJlZCIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBjKC0wLjMsMC4zKSxsaW5ldHlwZT0iZG90dGVkIixjb2xvdXI9ImRhcmsgcmVkIikrCiAgbGFicyh4PXBhc3RlMChnc3ViKCJjb21tb25fIiwiIixhcy5jaGFyYWN0ZXIoY29tcCR4KSkpLHk9Z3N1YigiY29tbW9uXyIsIiIsYXMuY2hhcmFjdGVyKGNvbXAkeSkpKSkKCiAgYXNzaWduKG5hbWVzX3Bsb3QyW2ldLGdncGxvdChuYW1lc19jb21wLGFlcyh4PWNvbnQxX3ZlYyx5PWNvbnQyX3ZlYyxjb2xvdXI9dmFyaWFibGUyKSkgKyBnZW9tX3BvaW50KCkrCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygtMC4zLDAuMyksbGluZXR5cGU9ImRvdHRlZCIsY29sb3VyPSJkYXJrIHJlZCIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBjKC0wLjMsMC4zKSxsaW5ldHlwZT0iZG90dGVkIixjb2xvdXI9ImRhcmsgcmVkIikrCiAgbGFicyh4PXBhc3RlMChnc3ViKCJjb21tb25fIiwiIixhcy5jaGFyYWN0ZXIoY29tcCR4KSkpLHk9Z3N1YigiY29tbW9uXyIsIiIsYXMuY2hhcmFjdGVyKGNvbXAkeSkpKSkKCnByaW50KGkpCiAgCn0KCmNvcl9kYXRhIDwtIGRhdGEuZnJhbWUoY29tcGFyaXNvbiA9IG5hbWVzKHNjb3IpLHJfc3F1YXJlZCA9IGRvLmNhbGwoYyxzY29yKSkgJT4lIAogIGFycmFuZ2Uocl9zcXVhcmVkKQpgYGAKCmBgYHtyIGZpZy53aWR0aD0xMixmaWcuaGVpZ2h0PTh9CmNvd3Bsb3Q6OnBsb3RfZ3JpZChwMSxwMixwMyxwNCxwNSxwNixucm93PTMpCmBgYAoKYGBge3J9CmtuaXRyOjprYWJsZShjb3JfZGF0YSkKYGBgCgoKIyMgQWxsIGNvbnRleHQgdG9nZXRoZXIKCmBgYHtyIGNvcl9hbGxfY29udGV4dHN9CmNvdiA8LSBjb3IoZmlsdGVyZWRfY29udlssbGlrZXJ0X3ZhcmlhYmxlczFdLG1ldGhvZCA9ICJwZWFyc29uIix1c2U9InBhaXJ3aXNlLmNvbXBsZXRlLm9icyIpCgpyb3dfaW5mb3MgPC0gZGF0YS5mcmFtZShWYXJpYWJsZXM9c2FwcGx5KHN0cnNwbGl0KGNvbG5hbWVzKGNvdiksc3BsaXQ9IlxcLiIpLGZ1bmN0aW9uKHgpIHhbMl0pKQpyb3dfaW5mb3MkVmFyaWFibGVzIDwtIGFzLmNoYXJhY3Rlcihyb3dfaW5mb3MkVmFyaWFibGVzKQpyb3duYW1lcyhyb3dfaW5mb3MpIDwtIHJvd25hbWVzKGNvdikKcm93X2luZm9zJFZhcmlhYmxlc1t3aGljaChpcy5uYShyb3dfaW5mb3MkVmFyaWFibGVzKSldIDwtIGMoIm5lY2Vzc2l0eSIsImVkdWNhdGVkIikKcm93X2luZm9zIDwtIHJvd19pbmZvc1tvcmRlcihyb3dfaW5mb3MkVmFyaWFibGVzKSwsZHJvcD1GQUxTRV0KCmFubl9jb2xfd2lkZSA8LSBkYXRhLmZyYW1lKFZhcmlhYmxlPXVuaXF1ZShyb3dfaW5mb3MkVmFyaWFibGVzKSkKYW5uX2NvbG9yc193aWRlIDwtIGxpc3QoVmFyaWFibGVzPWMoY29tbTE9IiNiZDAwMjYiLGVkdWNhdGVkPSJvcmFuZ2UiLCBpZDE9IiNmNmU4YzMiLGluc3RydTE9IiMzNTk3OGYiLG5lY2Vzc2l0eT0iI2IzNTgwNiIsaW50ZWdyMT0iIzM4NmNiMCIsaW50cjE9IiNmZmZmOTkiLG91Z2h0MT0iZ3JleSIscG9zdDE9ImJsYWNrIixwcm9mMT0icGluayIpKQoKZGlhZyhjb3YpIDwtIE5BCnBoZWF0bWFwKGNvdiwgbWFpbiA9ICJBbGwgQ29udGV4dHMiLGFubm90YXRpb25fbmFtZXNfcm93ID0gRkFMU0UsY2x1c3Rlcl9jb2xzPVRSVUUsY2x1c3Rlcl9yb3dzPVRSVUUsYW5ub3RhdGlvbl9jb2wgPSByb3dfaW5mb3NbLDEsZHJvcD1GQUxTRV0sIGFubm90YXRpb25fcm93ID0gcm93X2luZm9zWywxLGRyb3A9RkFMU0VdCiwgIGFubm90YXRpb25fY29sb3JzID0gYW5uX2NvbG9yc193aWRlLHNob3dfY29sbmFtZXMgPSBGQUxTRSxicmVha3MgPSBzZXEoLTAuNiwwLjcsbGVuZ3RoLm91dCA9IDUwKSx3aWR0aCA9IDcsaGVpZ2h0ID0gNyxjb2xvcj1jb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwobiA9IDcsIG5hbWUgPSAiUmRCdSIpKSg1MCkpCgpgYGAKCiMjIENvbXBhcmUgY29ycmVsYXRpb25zCgpgYGB7cn0KbGlicmFyeShHR2FsbHkpCmNvbWJpbmVfY29yIDwtIG1lcmdlKGRhdGFfY29yX2VuZ19pbl9pdGEsZGF0YV9jb3JfZW5nX2luX2dlcm0sYWxsID0gVFJVRSkKY29tYmluZV9jb3IxIDwtIG1lcmdlKGNvbWJpbmVfY29yLGRhdGFfY29yX2dlcm1faW5fYXUsYWxsID0gVFJVRSkKY29tYmluZV9jb3IyIDwtIG1lcmdlKGNvbWJpbmVfY29yMSxkYXRhX2Nvcl9pdGFfaW5fYXUsYWxsID0gVFJVRSkKY29tYmluZV9jb3IyIDwtIGNvbWJpbmVfY29yMiAlPiUgc2VwYXJhdGUodmFyMSxpbnRvPWMoIml0ZW0xIiwidmFyaWFibGUxIiksc2VwPSJbLl0iLHJlbW92ZT1GQUxTRSkgJT4lCiAgc2VwYXJhdGUodmFyMixpbnRvPWMoIml0ZW0yIiwidmFyaWFibGUyIiksc2VwPSJbLl0iLHJlbW92ZT1GQUxTRSkgJT4lCiAgdW5pdGUoZ3JvdXAsdmFyaWFibGUxLHZhcmlhYmxlMixzZXA9Ii4iKQoKcGFpcnMoY29tYmluZV9jb3IyWyxjKCJjb3JfZW5nX2luX2l0YSIsImNvcl9lbmdfaW5fZ2VybSIsImNvcl9nZXJtX2luX2F1IiwiY29yX2l0YV9pbl9hdSIpXSkKZ2dwYWlycyhjb21iaW5lX2NvcjJbLGMoImNvcl9lbmdfaW5faXRhIiwiY29yX2VuZ19pbl9nZXJtIiwiY29yX2dlcm1faW5fYXUiLCJjb3JfaXRhX2luX2F1IildKQoKYGBgCgoKIyMgQ29ycmVsYXRpb24gYmV0d2VlbiBjb3JyZWxhdGlvbiBpbiB0aGUgZGlmZmVyZW50IGNvbnRleHRzCgpXZSB3aWxsIHBlcmZvcm0gYW4gZXhwbG9yYXRvcnkgRkEgY29tYmluaW5nIGFsbCB0aGUgY29udGV4dHMgdG9nZXRoZXIuIFRoaXMgbWVhbnMgdGhhdCB3ZSBhcmUgYXNzdW1pbmcgdGhhdCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBpdGVtcyBhY3Jvc3MgY29udGV4dCBoYXMgdGhlIHNhbWUgZGlyZWN0aW9uIChkb2VzIG5vdCBoYXBwZW4gdGhhdCBjb3IoaXRlbTEsaXRlbTIpX2NvbnRleHQxID4gMCBhbmQgY29yKGl0ZW0xLGl0ZW0yKV9jb250ZXh0MiA8IDApLiAKCmBgYHtyIGZpZy53aWR0aD0xMCxmaWcuaGVpZ2h0PTEwfQpjb21tb24gPC0gcm93bmFtZXMoY292X0VuZ0l0YSlbcm93bmFtZXMoY292X0VuZ0l0YSkgJWluJSByb3duYW1lcyhjb3ZfSXRhQXVzKV0Kc3VtKHJvd25hbWVzKGNvdl9FbmdJdGEpICE9IHJvd25hbWVzKGNvdl9FbmdHZXJtKSkKc3VtKHJvd25hbWVzKGNvdl9FbmdJdGEpICE9IHJvd25hbWVzKGNvdl9HZXJtQXVzKSkKc3VtKHJvd25hbWVzKGNvdl9FbmdJdGEpICE9IHJvd25hbWVzKGNvdl9JdGFBdXMpKQpzdW0ocm93bmFtZXMoY292X0dlcm1BdXMpICE9IHJvd25hbWVzKGNvdl9JdGFBdXMpKQoKY29tbW9uX0VuZ0l0YSA8LSBjb3ZfRW5nSXRhW3Jvd25hbWVzKGNvdl9FbmdJdGEpICVpbiUgY29tbW9uLGNvbG5hbWVzKGNvdl9FbmdJdGEpICVpbiUgY29tbW9uXQpjb21tb25fRW5nR2VybSA8LSBjb3ZfRW5nR2VybVtyb3duYW1lcyhjb3ZfRW5nR2VybSkgJWluJSBjb21tb24sY29sbmFtZXMoY292X0VuZ0dlcm0pICVpbiUgY29tbW9uXQpjb21tb25fR2VybUF1cyA8LSBjb3ZfR2VybUF1c1tyb3duYW1lcyhjb3ZfR2VybUF1cykgJWluJSBjb21tb24sY29sbmFtZXMoY292X0dlcm1BdXMpICVpbiUgY29tbW9uXQpjb21tb25fSXRhQXVzIDwtIGNvdl9JdGFBdXNbcm93bmFtZXMoY292X0l0YUF1cykgJWluJSBjb21tb24sY29sbmFtZXMoY292X0l0YUF1cykgJWluJSBjb21tb25dCgpzdW0ocm93bmFtZXMoY29tbW9uX0VuZ0l0YSkgIT0gY29sbmFtZXMoY29tbW9uX0VuZ0l0YSkpCnN1bShyb3duYW1lcyhjb21tb25fRW5nR2VybSkgIT0gY29sbmFtZXMoY29tbW9uX0VuZ0dlcm0pKQpzdW0ocm93bmFtZXMoY29tbW9uX0dlcm1BdXMpICE9IGNvbG5hbWVzKGNvbW1vbl9HZXJtQXVzKSkKc3VtKHJvd25hbWVzKGNvbW1vbl9JdGFBdXMpICE9IGNvbG5hbWVzKGNvbW1vbl9JdGFBdXMpKQoKCnBhcihtZnJvdz1jKDIsMykpCnBsb3QoY29tbW9uX0VuZ0l0YSxjb21tb25fRW5nR2VybSkKYWJsaW5lKGg9YygwLDAuMyksdj1jKDAsMC4zKSxsdHk9Mixjb2wgPSAiZGFyayByZWQiKQphYmxpbmUoYT0wLGI9MSxsdHk9Mixjb2wgPSAiZGFyayByZWQiKQpwbG90KGNvbW1vbl9FbmdJdGEsY29tbW9uX0dlcm1BdXMpCmFibGluZShoPWMoMCwwLjMpLHY9YygwLDAuMyksbHR5PTIsY29sID0gImRhcmsgcmVkIikKYWJsaW5lKGE9MCxiPTEsbHR5PTIsY29sID0gImRhcmsgcmVkIikKcGxvdChjb21tb25fRW5nSXRhLGNvbW1vbl9JdGFBdXMpCmFibGluZShoPWMoMCwwLjMpLHY9YygwLDAuMyksbHR5PTIsY29sID0gImRhcmsgcmVkIikKYWJsaW5lKGE9MCxiPTEsbHR5PTIsY29sID0gImRhcmsgcmVkIikKCnBsb3QoY29tbW9uX0VuZ0dlcm0sY29tbW9uX0dlcm1BdXMpCmFibGluZShoPWMoMCwwLjMpLHY9YygwLDAuMyksbHR5PTIsY29sID0gImRhcmsgcmVkIikKYWJsaW5lKGE9MCxiPTEsbHR5PTIsY29sID0gImRhcmsgcmVkIikKcGxvdChjb21tb25fRW5nR2VybSxjb21tb25fSXRhQXVzKQphYmxpbmUoaD1jKDAsMC4zKSx2PWMoMCwwLjMpLGx0eT0yLGNvbCA9ICJkYXJrIHJlZCIpCmFibGluZShhPTAsYj0xLGx0eT0yLGNvbCA9ICJkYXJrIHJlZCIpCgpwbG90KGNvbW1vbl9HZXJtQXVzLGNvbW1vbl9JdGFBdXMpCmFibGluZShoPWMoMCwwLjMpLHY9YygwLDAuMyksbHR5PTIsY29sID0gImRhcmsgcmVkIikKYWJsaW5lKGE9MCxiPTEsbHR5PTIsY29sID0gImRhcmsgcmVkIikKCiMgTGFyZ2VzdCBkaWZmZXJlbmNlcwpsb3dfRW5nR2VybSA8LSBsb3dlci50cmkoY29tbW9uX0VuZ0dlcm0pCmNvbW1vbl9FbmdHZXJtWyFsb3dfRW5nR2VybV0gPC0gTkEKY29tbW9uX0dlcm1BdXNbIShsb3dlci50cmkoY29tbW9uX0dlcm1BdXMpKV0gPC0gTkEKY29tbW9uX0l0YUF1c1shKGxvd2VyLnRyaShjb21tb25fSXRhQXVzKSldIDwtIE5BCmNvbW1vbl9FbmdJdGFbIShsb3dlci50cmkoY29tbW9uX0VuZ0l0YSkpXSA8LSBOQQoKCm1hdCA8LSBkYXRhLmZyYW1lKGNvbW1vbl9FbmdHZXJtPWMoY29tbW9uX0VuZ0dlcm0pLAogICAgICAgICAgICAgICAgICBjb21tb25fRW5nSXRhPWMoY29tbW9uX0VuZ0l0YSksCiAgICAgICAgICAgICAgICAgIGNvbW1vbl9HZXJtQXVzID0gYyhjb21tb25fR2VybUF1cyksCiAgICAgICAgICAgICAgICAgIGNvbW1vbl9JdGFBdXMgPSBjKGNvbW1vbl9JdGFBdXMpLAogICAgICAgICAgICAgICAgICBjb21wYXJlID0gcGFzdGUocm93bmFtZXMoY29tbW9uX0VuZ0dlcm0pLGNvbG5hbWVzKGNvbW1vbl9FbmdHZXJtKSxzZXA9Ii4iKSkgJT4lCiAgZmlsdGVyKCFpcy5uYShjb21tb25fRW5nR2VybSkpICU+JQogIHNlcGFyYXRlKGNvbXBhcmUsaW50bz1jKCJpdGVtMSIsInZhcmlhYmxlMSIsIml0ZW0yIiwidmFyaWFibGUyIikscmVtb3ZlPUZBTFNFLHNlcD0iWy5dIikgJT4lCiAgdW5pdGUoZ3JvdXAsdmFyaWFibGUxLHZhcmlhYmxlMixzZXA9Ii4iKQoKbGlicmFyeShnZ3JlcGVsKQpnZ3Bsb3QobWF0LGFlcyh4PWNvbW1vbl9FbmdHZXJtLHk9Y29tbW9uX0dlcm1BdXMsbGFiZWw9Y29tcGFyZSxjb2xvdXI9Z3JvdXApKSArIGdlb21fcG9pbnQoYWxwaGE9MC41LHNpemU9MC44KSArIGdlb21fdGV4dChzaXplPTIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9YygwLDAuMyksbGluZXR5cGU9ImRvdHRlZCIsY29sb3VyPSJkYXJrIHJlZCIpICsKZ2VvbV92bGluZSh4aW50ZXJjZXB0PWMoMCwwLjMpLGxpbmV0eXBlPSJkb3R0ZWQiLGNvbG91cj0iZGFyayByZWQiKQoKCmdncGxvdChtYXQsYWVzKHg9Y29tbW9uX0VuZ0dlcm0seT1jb21tb25fSXRhQXVzLGxhYmVsPWNvbXBhcmUsY29sb3VyPWdyb3VwKSkgKyBnZW9tX3BvaW50KGFscGhhPTAuNSxzaXplPTAuOCkgKyBnZW9tX3RleHQoc2l6ZT0yKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PWMoMCwwLjMpLGxpbmV0eXBlPSJkb3R0ZWQiLGNvbG91cj0iZGFyayByZWQiKSArCmdlb21fdmxpbmUoeGludGVyY2VwdD1jKDAsMC4zKSxsaW5ldHlwZT0iZG90dGVkIixjb2xvdXI9ImRhcmsgcmVkIikKCmdncGxvdChtYXQsYWVzKHg9Y29tbW9uX0VuZ0dlcm0seT1jb21tb25fRW5nSXRhLGxhYmVsPWNvbXBhcmUsY29sb3VyPWdyb3VwKSkgKyBnZW9tX3BvaW50KGFscGhhPTAuNSxzaXplPTAuOCkgKyBnZW9tX3RleHQoc2l6ZT0yKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PWMoMCwwLjMpLGxpbmV0eXBlPSJkb3R0ZWQiLGNvbG91cj0iZGFyayByZWQiKSArCmdlb21fdmxpbmUoeGludGVyY2VwdD1jKDAsMC4zKSxsaW5ldHlwZT0iZG90dGVkIixjb2xvdXI9ImRhcmsgcmVkIikKCmBgYAoKCgojIEV2YWx1YXRlIGludGVybmFsIGNvbnNpc3RlbmN5IG9mIGtub3duIGNvbnN0cnVjdHMgd2l0aCBhbHBoYQoKYGBge3J9CnNldHMgPC0gbGlzdChpZC52YXI9bGlrZXJ0X3ZhcmlhYmxlczFbZ3JlcCgiXFwuaWQxJCIsbGlrZXJ0X3ZhcmlhYmxlczEpXSwKICAgICAgICAgICAgIG91Z2h0LnZhcj1saWtlcnRfdmFyaWFibGVzMVtncmVwKCJcXC5vdWdodDEkIixsaWtlcnRfdmFyaWFibGVzMSldLAogICAgICAgICAgICAgaW50ci52YXI9bGlrZXJ0X3ZhcmlhYmxlczFbZ3JlcCgiXFwuaW50cjEkIixsaWtlcnRfdmFyaWFibGVzMSldLAogICAgICAgICAgICAgaW5zdHJ1LnZhcj1saWtlcnRfdmFyaWFibGVzMVtncmVwKCJcXC5pbnN0cnUxJCIsbGlrZXJ0X3ZhcmlhYmxlczEpXSwKICAgICAgICAgICAgIGludGVncjEudmFyPWxpa2VydF92YXJpYWJsZXMxW2dyZXAoIlxcLmludGVncjEkIixsaWtlcnRfdmFyaWFibGVzMSldLAogICAgICAgICAgICAgcHJvZi52YXI9bGlrZXJ0X3ZhcmlhYmxlczFbZ3JlcCgiXFwucHJvZjEkIixsaWtlcnRfdmFyaWFibGVzMSldLAogICAgICAgICAgICAgcG9zdC52YXI9bGlrZXJ0X3ZhcmlhYmxlczFbZ3JlcCgiXFwucG9zdDEkIixsaWtlcnRfdmFyaWFibGVzMSldLAogICAgICAgICAgICAgY29tbS52YXI9bGlrZXJ0X3ZhcmlhYmxlczFbZ3JlcCgiXFwuY29tbTEkIixsaWtlcnRfdmFyaWFibGVzMSldKQogICAgICAgICAgICAgIAoKZ2V0X2FscGhhIDwtIGZ1bmN0aW9uKGRhdGFNb3QsCiAgICAgICAgICAgICAgICAgICAgICB2YXI9c2V0cyRpZC52YXIpewogIHZhcl9hbHBoYSA8LSBwc3ljaDo6YWxwaGEoZGF0YU1vdFssdmFyXSkKICBkYXRhZiA8LSBkYXRhLmZyYW1lKGFscGhhPXZhcl9hbHBoYSR0b3RhbCwKICAgICAgICAgICAgICAgICAgICBkcm9wID0gdmFyX2FscGhhJGFscGhhLmRyb3ApCiAgcm93bmFtZXMoZGF0YWYpIDwtIHJvd25hbWVzKHZhcl9hbHBoYSRhbHBoYS5kcm9wKQogIHJldHVybihkYXRhZikKfQoKIyAiSXRhbGlhbiBpbiBBdXN0cmFsaWEiCml0YV9pbl9hdV9kZiA8LSBmaWx0ZXJlZF9jb252W2ZpbHRlcmVkX2NvbnYkQ29udGV4dCA9PSAiSXRhbGlhbiBpbiBBdXN0cmFsaWEiLF0KbGlzdF9vZl9pdGFfaW5fYXUgPC0gbGFwcGx5KHNldHMsZnVuY3Rpb24oeCkgewogIGdldF9hbHBoYShkYXRhTW90PWl0YV9pbl9hdV9kZix2YXI9eCl9KQppdGFfaW5fYXUgPC0gZG8uY2FsbChyYmluZCxsaXN0X29mX2l0YV9pbl9hdSkKaXRhX2luX2F1JHZhciA8LSBzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMoaXRhX2luX2F1KSxzcGxpdD0iXFwuIiksZnVuY3Rpb24oeCkgeFsxXSkgCml0YV9pbl9hdSR2YXIuZnVsbCA8LSBzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMoaXRhX2luX2F1KSxzcGxpdD0iXFwuIiksZnVuY3Rpb24oeCkgeFszXSkgCml0YV9pbl9hdSRDb250ZXh0IDwtICJJdGFsaWFuIGluIEF1c3RyYWxpYSIKcm93bmFtZXMoaXRhX2luX2F1KSA8LSBOVUxMCgojICJHZXJtYW4gaW4gQXVzdHJhbGlhIgpnZXJtX2luX2F1IDwtIGRvLmNhbGwocmJpbmQsbGFwcGx5KHNldHMsZnVuY3Rpb24oeCkgewogIGdldF9hbHBoYShkYXRhTW90ID1maWx0ZXJlZF9jb252W2ZpbHRlcmVkX2NvbnYkQ29udGV4dCA9PSAiR2VybWFuIGluIEF1c3RyYWxpYSIsXSwKICAgICAgICAgICAgICAgICAgICAgIHZhcj14KX0pKQpnZXJtX2luX2F1JHZhciA8LSBzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMoZ2VybV9pbl9hdSksc3BsaXQ9IlxcLiIpLGZ1bmN0aW9uKHgpIHhbMV0pIApnZXJtX2luX2F1JHZhci5mdWxsIDwtIHNhcHBseShzdHJzcGxpdChyb3duYW1lcyhnZXJtX2luX2F1KSxzcGxpdD0iXFwuIiksZnVuY3Rpb24oeCkgeFszXSkgCmdlcm1faW5fYXUkQ29udGV4dCA8LSAiR2VybWFuIGluIEF1c3RyYWxpYSIKcm93bmFtZXMoZ2VybV9pbl9hdSkgPC0gTlVMTAoKIyAiRW5nbGlzaCBpbiBHZXJtYW55IgplbmdfaW5fZ2VybSA8LSBkby5jYWxsKHJiaW5kLGxhcHBseShzZXRzWyEobmFtZXMoc2V0cykgJWluJSAiY29tbS52YXIiKV0sZnVuY3Rpb24oeCkgewogIGdldF9hbHBoYShkYXRhTW90PWZpbHRlcmVkX2NvbnZbZmlsdGVyZWRfY29udiRDb250ZXh0ID09ICJFbmdsaXNoIGluIEdlcm1hbnkiLF0sCiAgICAgICAgICAgICAgICAgICAgICB2YXI9eCl9KSkKCiMgdGhlIG9uZXMgdGhhdCBtYWtlcyBpc3N1ZXMKZ2V0X2FscGhhKGRhdGFNb3Q9ZmlsdGVyZWRfY29udltmaWx0ZXJlZF9jb252JENvbnRleHQgPT0gIkVuZ2xpc2ggaW4gR2VybWFueSIsXSwKICAgICAgICAgICAgICAgICAgICAgIHZhcj1zZXRzJG91Z2h0LnZhcikKCmVuZ19pbl9nZXJtJHZhciA8LSBzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMoZW5nX2luX2dlcm0pLHNwbGl0PSJcXC4iKSxmdW5jdGlvbih4KSB4WzFdKSAKZW5nX2luX2dlcm0kdmFyLmZ1bGwgPC0gc2FwcGx5KHN0cnNwbGl0KHJvd25hbWVzKGVuZ19pbl9nZXJtKSxzcGxpdD0iXFwuIiksZnVuY3Rpb24oeCkgeFszXSkgCmVuZ19pbl9nZXJtJENvbnRleHQgPC0gIkVuZ2xpc2ggaW4gR2VybWFueSIKcm93bmFtZXMoZW5nX2luX2dlcm0pIDwtIE5VTEwKCiMgIkVuZ2xpc2ggaW4gSXRhbHkiCmVuZ19pbl9pdGEgPC0gZG8uY2FsbChyYmluZCxsYXBwbHkoc2V0c1shKG5hbWVzKHNldHMpICVpbiUgImNvbW0udmFyIildLGZ1bmN0aW9uKHgpIHsKICBnZXRfYWxwaGEoZGF0YU1vdD1maWx0ZXJlZF9jb252W2ZpbHRlcmVkX2NvbnYkQ29udGV4dCA9PSAiRW5nbGlzaCBpbiBJdGFseSIsXSwKICAgICAgICAgICAgICAgICAgICAgIHZhcj14KX0pKQplbmdfaW5faXRhJHZhciA8LSBzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMoZW5nX2luX2l0YSksc3BsaXQ9IlxcLiIpLGZ1bmN0aW9uKHgpIHhbMV0pIAplbmdfaW5faXRhJHZhci5mdWxsIDwtIHNhcHBseShzdHJzcGxpdChyb3duYW1lcyhlbmdfaW5faXRhKSxzcGxpdD0iXFwuIiksZnVuY3Rpb24oeCkgeFszXSkgCmVuZ19pbl9pdGEkQ29udGV4dCA8LSAiRW5nbGlzaCBpbiBJdGFseSIKcm93bmFtZXMoZW5nX2luX2l0YSkgPC0gTlVMTAoKCiMgY29tYmluZQpmdWxsX2FscGhhIDwtIHJiaW5kKGVuZ19pbl9pdGEsZW5nX2luX2dlcm0sZ2VybV9pbl9hdSxpdGFfaW5fYXUpCgpgYGAKCi0gUGxvdCBhbHBoYSBieSB2YXJpYWJsZQoKYGBge3IgYWxwaGFfY2hyb25iYWNoX2J5X2NvbnRleHR9CgpmdWxsX2FscGhhICU+JSBncm91cF9ieShDb250ZXh0LHZhcikgJT4lIAogIHN1bW1hcmlzZShzdC5hbHBoYSA9IHVuaXF1ZShhbHBoYS5zdGQuYWxwaGEpLAogICAgICAgICAgICBHNj11bmlxdWUoYWxwaGEuRzYuc21jLikpICU+JQogIGdncGxvdCguLGFlcyh4PXZhcix5PXN0LmFscGhhLGNvbG91cj1Db250ZXh0KSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoYWVzKGdyb3VwPUNvbnRleHQpKSArIHRoZW1lX2J3KCkKCmBgYAoKCmBgYHtyIGZpZy5oZWlnaHQ9MTgsZmlnLndpZHRoPTE0fQphbGxfbWVsdCA8LSBhbGxfbWVsdCAlPiUgc2VwYXJhdGUodmFyaWFibGUsaW50bz1jKCJpdGVtIiwidHlwZSIpLHNlcD0iXFwuIixyZW1vdmU9RkFMU0UpCnAxPWdncGxvdChhbGxfbWVsdCxhZXMoeD12YXJpYWJsZSxmaWxsPXZhbHVlKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJzdGFjayIpICsgCiAgZmFjZXRfZ3JpZChDb250ZXh0fnR5cGUsc2NhbGVzID0gImZyZWUiKSArIGdndGl0bGUoIkZpbHRlcmVkIGRhdGFzZXQiKSt0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT04KSkrdGhlbWVfYncoKQoKcDI9Z2dwbG90KGZ1bGxfYWxwaGEsYWVzKHg9dmFyLmZ1bGwseT1kcm9wLnN0ZC5hbHBoYSxjb2xvdXI9Q29udGV4dCkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9saW5lKGFlcyhncm91cD1Db250ZXh0KSkgKyB0aGVtZV9idygpICsgZmFjZXRfd3JhcCh+dmFyLHNjYWxlcz0iZnJlZSIpCgpwND1nZ3Bsb3QoZnVsbF9hbHBoYSxhZXMoeD12YXIuZnVsbCx5PWRyb3AuYXZlcmFnZV9yLGNvbG91cj1Db250ZXh0KSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoYWVzKGdyb3VwPUNvbnRleHQpKSArIHRoZW1lX2J3KCkgKyBmYWNldF93cmFwKH52YXIsc2NhbGVzPSJmcmVlIikKCnAzPWZ1bGxfYWxwaGEgJT4lIGdyb3VwX2J5KENvbnRleHQsdmFyKSAlPiUgCiAgc3VtbWFyaXNlKHN0LmFscGhhID0gdW5pcXVlKGFscGhhLnN0ZC5hbHBoYSksCiAgICAgICAgICAgIEc2PXVuaXF1ZShhbHBoYS5HNi5zbWMuKSkgJT4lCiAgZ2dwbG90KC4sYWVzKHg9dmFyLHk9c3QuYWxwaGEsY29sb3VyPUNvbnRleHQpKSArIGdlb21fcG9pbnQoKSArIGdlb21fbGluZShhZXMoZ3JvdXA9Q29udGV4dCkpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSxheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9OCkpICsgdGhlbWVfYncoKQoKCmNvd3Bsb3Q6OnBsb3RfZ3JpZChwMixwMyxucm93PTIpCgpgYGAKCgpgYGB7cn0KZ2dwbG90KGZ1bGxfYWxwaGFbZnVsbF9hbHBoYSR2YXIgPT0gImluc3RydSIsXSxhZXMoeD12YXIuZnVsbCx5PWRyb3Auc3RkLmFscGhhLGNvbG91cj1Db250ZXh0KSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX2xpbmUoYWVzKGdyb3VwPUNvbnRleHQpKSArIHRoZW1lX2J3KCkgKyBsYWJzKHkgPSAiRHJvcCBJdGVtIC0gQ2hyb25iYWNoJ3MgQWxwaGEiLCB4ID0gIkl0ZW1zIikgKyBnZ3RpdGxlKCJWYXJpYWJsZTogSW5zdHJ1bWVudGFsIE9yaWVudGF0aW9uIikKCmBgYAoK